diff --git a/libraries/chain/controller.cpp b/libraries/chain/controller.cpp index f5c7689513..e616b55f33 100644 --- a/libraries/chain/controller.cpp +++ b/libraries/chain/controller.cpp @@ -1117,13 +1117,6 @@ struct controller_impl { return prev->block_num(); } - // returns 0 for legacy - size_t fork_db_savanna_size() const { - return fork_db.apply_s([&](const auto& forkdb) { - return forkdb.size(); - }); - } - bool fork_db_block_exists( const block_id_type& id ) const { return fork_db.apply([&](const auto& forkdb) { return forkdb.block_exists(id); @@ -4840,6 +4833,19 @@ struct controller_impl { return conf.block_validation_mode == validation_mode::LIGHT || conf.trusted_producers.count(producer); } + int32_t max_reversible_blocks_allowed() const { + if (conf.max_reversible_blocks == 0) + return std::numeric_limits::max(); + + return fork_db.apply( + [&](const fork_database_legacy_t& forkdb) { + return std::numeric_limits::max(); + }, + [&](const fork_database_if_t& forkdb) { + return conf.max_reversible_blocks - forkdb.size(); + }); + } + bool should_terminate(block_num_type reversible_block_num) const { assert(reversible_block_num > 0); if (conf.terminate_at_block > 0 && conf.terminate_at_block <= reversible_block_num) { @@ -4847,9 +4853,9 @@ struct controller_impl { ("n", reversible_block_num)("num", conf.terminate_at_block) ); return true; } - if (conf.max_reversible_blocks > 0 && fork_db_savanna_size() >= conf.max_reversible_blocks) { + if (max_reversible_blocks_allowed() <= 0) { elog("Exceeded max reversible blocks allowed, fork db size ${s} >= max-reversible-blocks ${m}", - ("s", fork_db_savanna_size())("m", conf.max_reversible_blocks)); + ("s", fork_db_size())("m", conf.max_reversible_blocks)); return true; } return false; @@ -5660,6 +5666,10 @@ bool controller::should_terminate() const { return my->should_terminate(); } +int32_t controller:: max_reversible_blocks_allowed() const { + return my->max_reversible_blocks_allowed(); +} + const apply_handler* controller::find_apply_handler( account_name receiver, account_name scope, action_name act ) const { auto native_handler_scope = my->apply_handlers.find( receiver ); diff --git a/libraries/chain/include/eosio/chain/controller.hpp b/libraries/chain/include/eosio/chain/controller.hpp index 297b633e8b..6e4ce2b061 100644 --- a/libraries/chain/include/eosio/chain/controller.hpp +++ b/libraries/chain/include/eosio/chain/controller.hpp @@ -95,7 +95,7 @@ namespace eosio::chain { uint32_t sig_cpu_bill_pct = chain::config::default_sig_cpu_bill_pct; uint16_t chain_thread_pool_size = chain::config::default_controller_thread_pool_size; uint16_t vote_thread_pool_size = 0; - uint32_t max_reversible_blocks = chain::config::default_max_reversible_blocks; + int32_t max_reversible_blocks = chain::config::default_max_reversible_blocks; bool read_only = false; bool force_all_checks = false; bool disable_replay_opts = false; @@ -396,6 +396,11 @@ namespace eosio::chain { /// not-thread-safe bool should_terminate() const; + /// Difference between max-reversible-blocks and fork database size. + /// Can return MAX_INT32 if disabled or pre-Savanna + /// @return the number of reversible blocks still allowed + int32_t max_reversible_blocks_allowed() const; + void set_subjective_cpu_leeway(fc::microseconds leeway); std::optional get_subjective_cpu_leeway() const; void set_greylist_limit( uint32_t limit ); diff --git a/libraries/chain/include/eosio/chain/fork_database.hpp b/libraries/chain/include/eosio/chain/fork_database.hpp index 6c59ba652a..c0d12873ab 100644 --- a/libraries/chain/include/eosio/chain/fork_database.hpp +++ b/libraries/chain/include/eosio/chain/fork_database.hpp @@ -263,7 +263,7 @@ namespace eosio::chain { } /// @param legacy_f the lambda to execute if in legacy mode - /// @param savanna_f the lambda to execute if in savanna instant-finality mode + /// @param savanna_f the lambda to execute if in savanna mode template R apply(const LegacyF& legacy_f, const SavannaF& savanna_f) { if constexpr (std::is_same_v) { @@ -281,6 +281,25 @@ namespace eosio::chain { } } + /// @param legacy_f the lambda to execute if in legacy mode + /// @param savanna_f the lambda to execute if in savanna mode + template + R apply(const LegacyF& legacy_f, const SavannaF& savanna_f) const { + if constexpr (std::is_same_v) { + if (in_use.load() == in_use_t::legacy) { + legacy_f(fork_db_l); + } else { + savanna_f(fork_db_s); + } + } else { + if (in_use.load() == in_use_t::legacy) { + return legacy_f(fork_db_l); + } else { + return savanna_f(fork_db_s); + } + } + } + // Update max_supported_version if the persistent file format changes. static constexpr uint32_t min_supported_version = 1; static constexpr uint32_t max_supported_version = 2; diff --git a/plugins/chain_plugin/chain_plugin.cpp b/plugins/chain_plugin/chain_plugin.cpp index b46edf25c0..4448e69519 100644 --- a/plugins/chain_plugin/chain_plugin.cpp +++ b/plugins/chain_plugin/chain_plugin.cpp @@ -361,7 +361,7 @@ void chain_plugin::set_program_options(options_description& cli, options_descrip "'none' - EOS VM OC tier-up is completely disabled.\n") #endif ("enable-account-queries", bpo::value()->default_value(false), "enable queries to find accounts by various metadata.") - ("max-reversible-blocks", bpo::value()->default_value(config::default_max_reversible_blocks), + ("max-reversible-blocks", bpo::value()->default_value(config::default_max_reversible_blocks), "Approximate maximum allowed reversible blocks before shutdown. Will shut down if limit reached. Specify 0 to disable.") ("transaction-retry-max-storage-size-gb", bpo::value(), "Maximum size (in GiB) allowed to be allocated for the Transaction Retry feature. Setting above 0 enables this feature.") @@ -954,7 +954,11 @@ void chain_plugin_impl::plugin_initialize(const variables_map& options) { account_queries_enabled = options.at("enable-account-queries").as(); - chain_config->max_reversible_blocks = options.at("max-reversible-blocks").as(); + chain_config->max_reversible_blocks = options.at("max-reversible-blocks").as(); + if (chain_config->max_reversible_blocks == -1) // allow -1 or 0 for disable + chain_config->max_reversible_blocks = 0; + EOS_ASSERT(chain_config->max_reversible_blocks >= 0, plugin_config_exception, + "max-reversible-blocks ${m} must be > 0", ("m", chain_config->max_reversible_blocks)); chain_config->integrity_hash_on_start = options.at("integrity-hash-on-start").as(); chain_config->integrity_hash_on_stop = options.at("integrity-hash-on-stop").as(); diff --git a/plugins/net_plugin/net_plugin.cpp b/plugins/net_plugin/net_plugin.cpp index 2a82681d18..f010155c6d 100644 --- a/plugins/net_plugin/net_plugin.cpp +++ b/plugins/net_plugin/net_plugin.cpp @@ -227,7 +227,6 @@ namespace eosio { const uint32_t sync_fetch_span {0}; const uint32_t sync_peer_limit {0}; - const size_t max_reversible_blocks {0}; alignas(hardware_destructive_interference_sz) std::atomic sync_state{in_sync}; @@ -259,7 +258,7 @@ namespace eosio { immediately, // closing connection immediately handshake // sending handshake message }; - explicit sync_manager( uint32_t span, uint32_t sync_peer_limit, size_t max_reversible_blocks, uint32_t min_blocks_distance ); + explicit sync_manager( uint32_t span, uint32_t sync_peer_limit, uint32_t min_blocks_distance ); static void send_handshakes(); bool syncing_from_peer() const { return sync_state == lib_catchup; } bool is_in_sync() const { return sync_state == in_sync; } @@ -1989,30 +1988,30 @@ namespace eosio { } //----------------------------------------------------------- - sync_manager::sync_manager( uint32_t span, uint32_t sync_peer_limit, size_t max_reversible_blocks, uint32_t min_blocks_distance ) + sync_manager::sync_manager( uint32_t span, uint32_t sync_peer_limit, uint32_t min_blocks_distance ) :sync_known_lib_num( 0 ) ,sync_last_requested_num( 0 ) ,sync_next_expected_num( 1 ) ,sync_source() ,sync_fetch_span( span ) ,sync_peer_limit( sync_peer_limit ) - ,max_reversible_blocks(max_reversible_blocks) ,sync_state(in_sync) ,min_blocks_distance(min_blocks_distance) { } uint32_t sync_manager::active_sync_fetch_span() const { - auto fork_db_size = my_impl->chain_plug->chain().fork_db_size(); - int32_t reversible_remaining = max_reversible_blocks - fork_db_size - 1; + int32_t reversible_remaining = my_impl->chain_plug->chain().max_reversible_blocks_allowed(); if (reversible_remaining <= 0) { - fc_wlog(logger, "max-reversible-blocks ${m} exceeded, remaining ${r}, fork_db_size ${fs}", - ("m", max_reversible_blocks)("r", reversible_remaining)("fs", fork_db_size)); + auto fork_db_size = my_impl->chain_plug->chain().fork_db_size(); + fc_wlog(logger, "max-reversible-blocks exceeded by ${ex}, fork_db_size ${fs}", + ("ex", -reversible_remaining)("fs", fork_db_size)); reversible_remaining = 0; } if (reversible_remaining < sync_fetch_span) { - fc_wlog(logger, "sync-fetch-span ${sfs} restricted to ${r} by max-reversible-blocks ${m}, fork_db_size ${fs}", - ("sfs", sync_fetch_span)("r", reversible_remaining)("m", max_reversible_blocks)("fs", fork_db_size)); + auto fork_db_size = my_impl->chain_plug->chain().fork_db_size(); + fc_wlog(logger, "sync-fetch-span ${sfs} restricted to ${r} by max-reversible-blocks, fork_db_size ${fs}", + ("sfs", sync_fetch_span)("r", reversible_remaining)("fs", fork_db_size)); return reversible_remaining; } return sync_fetch_span; @@ -4297,7 +4296,6 @@ namespace eosio { sync_master = std::make_unique( options.at( "sync-fetch-span" ).as(), options.at( "sync-peer-limit" ).as(), - chain_plug->chain_config().max_reversible_blocks, min_blocks_distance); connections.init( std::chrono::milliseconds( options.at("p2p-keepalive-interval-ms").as() * 2 ), diff --git a/tests/nodeos_startup_catchup.py b/tests/nodeos_startup_catchup.py index dabedb2120..625535799c 100755 --- a/tests/nodeos_startup_catchup.py +++ b/tests/nodeos_startup_catchup.py @@ -67,6 +67,8 @@ specificExtraNodeosArgs[pnodes+7] = f' --sync-fetch-span 1597 ' specificExtraNodeosArgs[pnodes+8] = f' --sync-fetch-span 6765 ' specificExtraNodeosArgs[pnodes+9] = f' --sync-fetch-span 28657 ' + if not activateIF: + specificExtraNodeosArgs[pnodes+9] += " --max-reversible-blocks 2 " # should be ignored for pre-savanna blocks specificExtraNodeosArgs[pnodes+10] = f' --sync-fetch-span 89 --read-mode irreversible ' specificExtraNodeosArgs[pnodes+11] = f' --sync-fetch-span 377 --read-mode irreversible ' if cluster.launch(prodCount=prodCount, specificExtraNodeosArgs=specificExtraNodeosArgs, activateIF=activateIF, onlyBios=False,