Skip to content

Commit

Permalink
Merge remote-tracking branch 'spring/release/1.0' into GH-641-max-rev…
Browse files Browse the repository at this point in the history
…ersible-blocks-block-production-main
  • Loading branch information
heifner committed Aug 27, 2024
2 parents 86b003e + 511eabe commit fdb4e46
Show file tree
Hide file tree
Showing 9 changed files with 19 additions and 94 deletions.
22 changes: 0 additions & 22 deletions libraries/chain/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4833,31 +4833,13 @@ 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<int32_t>::max();

return fork_db.apply<int32_t>(
[&](const fork_database_legacy_t& forkdb) {
return std::numeric_limits<int32_t>::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) {
ilog("Block ${n} reached configured maximum block ${num}; terminating",
("n", reversible_block_num)("num", conf.terminate_at_block) );
return true;
}
if (max_reversible_blocks_allowed() <= 0) {
elog("Exceeded max reversible blocks allowed, fork db size ${s} >= max-reversible-blocks ${m}",
("s", fork_db_size())("m", conf.max_reversible_blocks));
return true;
}
return false;
}

Expand Down Expand Up @@ -5666,10 +5648,6 @@ 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 );
Expand Down
3 changes: 2 additions & 1 deletion libraries/chain/include/eosio/chain/block_handle.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ struct block_handle {

bool is_valid() const { return !_bsp.valueless_by_exception() && std::visit([](const auto& bsp) { return !!bsp; }, _bsp); }

uint32_t block_num() const { return std::visit([](const auto& bsp) { return bsp->block_num(); }, _bsp); }
block_num_type block_num() const { return std::visit([](const auto& bsp) { return bsp->block_num(); }, _bsp); }
block_num_type irreversible_blocknum() const { return std::visit([](const auto& bsp) { return bsp->irreversible_blocknum(); }, _bsp); }
block_timestamp_type timestamp() const { return std::visit([](const auto& bsp) { return bsp->timestamp(); }, _bsp); };
time_point block_time() const { return std::visit([](const auto& bsp) { return time_point{bsp->timestamp()}; }, _bsp); };
const block_id_type& id() const { return std::visit<const block_id_type&>([](const auto& bsp) -> const block_id_type& { return bsp->id(); }, _bsp); }
Expand Down
8 changes: 1 addition & 7 deletions libraries/chain/include/eosio/chain/controller.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ 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;
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;
Expand Down Expand Up @@ -392,15 +391,10 @@ namespace eosio::chain {

db_read_mode get_read_mode()const;
validation_mode get_validation_mode()const;
/// @return true if terminate-at-block reached, or max-reversible-blocks reached
/// @return true if terminate-at-block reached
/// 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<fc::microseconds> get_subjective_cpu_leeway() const;
void set_greylist_limit( uint32_t limit );
Expand Down
8 changes: 0 additions & 8 deletions plugins/chain_plugin/chain_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -361,8 +361,6 @@ 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<bool>()->default_value(false), "enable queries to find accounts by various metadata.")
("max-reversible-blocks", bpo::value<int32_t>()->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<uint64_t>(),
"Maximum size (in GiB) allowed to be allocated for the Transaction Retry feature. Setting above 0 enables this feature.")
("transaction-retry-interval-sec", bpo::value<uint32_t>()->default_value(20),
Expand Down Expand Up @@ -954,12 +952,6 @@ void chain_plugin_impl::plugin_initialize(const variables_map& options) {

account_queries_enabled = options.at("enable-account-queries").as<bool>();

chain_config->max_reversible_blocks = options.at("max-reversible-blocks").as<int32_t>();
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<bool>();
chain_config->integrity_hash_on_stop = options.at("integrity-hash-on-stop").as<bool>();

Expand Down
34 changes: 3 additions & 31 deletions plugins/net_plugin/net_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,6 @@ namespace eosio {
void start_sync( const connection_ptr& c, uint32_t target ); // locks mutex
bool sync_recently_active() const;
bool verify_catchup( const connection_ptr& c, uint32_t num, const block_id_type& id ); // locks mutex
uint32_t active_sync_fetch_span(bool log) const;
public:
enum class closing_mode {
immediately, // closing connection immediately
Expand Down Expand Up @@ -2001,31 +2000,6 @@ namespace eosio {
{
}

uint32_t sync_manager::active_sync_fetch_span(bool log) const {
const uint32_t constrained_reversible_remaining = [&]() -> uint32_t {
const int32_t reversible_remaining = my_impl->chain_plug->chain().max_reversible_blocks_allowed();
if (reversible_remaining <= 0) {
if (log) {
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));
}
return 0;
}
return reversible_remaining;
}();

if (constrained_reversible_remaining < sync_fetch_span) {
if (log) {
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", constrained_reversible_remaining)("fs", fork_db_size));
}
return constrained_reversible_remaining;
}
return sync_fetch_span;
}

constexpr auto sync_manager::stage_str(stages s) {
switch (s) {
case in_sync : return "in sync";
Expand Down Expand Up @@ -2169,8 +2143,7 @@ namespace eosio {
bool request_sent = false;
if( sync_last_requested_num != sync_known_lib_num ) {
uint32_t start = sync_next_expected_num;
auto fetch_span = active_sync_fetch_span(true);
uint32_t end = start + fetch_span - 1;
uint32_t end = start + sync_fetch_span - 1;
if( end > sync_known_lib_num )
end = sync_known_lib_num;
if( end > 0 && end >= start ) {
Expand Down Expand Up @@ -2211,10 +2184,9 @@ namespace eosio {
bool sync_manager::is_sync_request_ahead_allowed(block_num_type blk_num) const REQUIRES(sync_mtx) {
if (blk_num >= sync_last_requested_num) {
// do not allow to get too far ahead (sync_fetch_span) of chain head
auto fetch_span = active_sync_fetch_span(false);
// use chain head instead of fork head so we do not get too far ahead of applied blocks
uint32_t head = my_impl->get_chain_head_num();
if (blk_num < head + fetch_span)
if (blk_num < head + sync_fetch_span)
return true;
}
return false;
Expand Down Expand Up @@ -2592,7 +2564,7 @@ namespace eosio {
// block was not applied, possibly because we already have the block
fc_dlog(logger, "Requesting ${fs} blocks ahead, head: ${h} fhead ${fh} blk_num: ${bn} sync_next_expected_num ${nen} "
"sync_last_requested_num: ${lrn}, sync_last_requested_block: ${lrb}",
("fs", active_sync_fetch_span(false))("h", my_impl->get_chain_head_num())("fh", my_impl->get_fork_head_num())
("fs", sync_fetch_span)("h", my_impl->get_chain_head_num())("fh", my_impl->get_fork_head_num())
("bn", blk_num)("nen", sync_next_expected_num)
("lrn", sync_last_requested_num)("lrb", c->sync_last_requested_block));
request_next_chunk();
Expand Down
13 changes: 12 additions & 1 deletion plugins/producer_plugin/producer_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,7 @@ class producer_plugin_impl : public std::enable_shared_from_this<producer_plugin
std::atomic<fc::time_point> _last_producer_vote_received;
fc::microseconds _production_pause_vote_timeout;
fc::microseconds _max_irreversible_block_age_us;
block_num_type _max_reversible_blocks{0};
// produce-block-offset is in terms of the complete round, internally use calculated value for each block of round
fc::microseconds _produce_block_cpu_effort;
fc::time_point _pending_block_deadline;
Expand Down Expand Up @@ -1169,6 +1170,8 @@ void producer_plugin::set_program_options(
"Setting this value (in milliseconds) will restrict the allowed transaction execution time to a value potentially lower than the on-chain consensus max_transaction_cpu_usage value.")
("max-irreversible-block-age", bpo::value<int32_t>()->default_value( -1 ),
"Limits the maximum age (in seconds) of the DPOS Irreversible Block for a chain this node will produce blocks on (use negative value to indicate unlimited)")
("max-reversible-blocks", bpo::value<uint32_t>()->default_value(config::default_max_reversible_blocks),
"Maximum allowed reversible blocks beyond irreversible before block production is paused. Specify 0 to disable.")
("producer-name,p", boost::program_options::value<vector<string>>()->composing()->multitoken(),
"ID of producer controlled by this node (e.g. inita; may specify multiple times)")
("signature-provider", boost::program_options::value<vector<string>>()->composing()->multitoken()->default_value(
Expand Down Expand Up @@ -1308,6 +1311,8 @@ void producer_plugin_impl::plugin_initialize(const boost::program_options::varia

_max_irreversible_block_age_us = fc::seconds(options.at("max-irreversible-block-age").as<int32_t>());

_max_reversible_blocks = options.at("max-reversible-blocks").as<uint32_t>();

auto max_incoming_transaction_queue_size = options.at("incoming-transaction-queue-size-mb").as<uint16_t>() * 1024 * 1024;

EOS_ASSERT(max_incoming_transaction_queue_size > 0, plugin_config_exception,
Expand Down Expand Up @@ -1930,7 +1935,8 @@ producer_plugin_impl::start_block_result producer_plugin_impl::start_block() {
return start_block_result::failed;
}

block_num_type head_block_num = chain.head().block_num();
block_handle head = chain.head();
block_num_type head_block_num = head.block_num();
const fc::time_point now = fc::time_point::now();
const block_timestamp_type block_time = calculate_pending_block_time();
const uint32_t pending_block_num = head_block_num + 1;
Expand Down Expand Up @@ -1976,6 +1982,11 @@ producer_plugin_impl::start_block_result producer_plugin_impl::start_block() {
("ov", _last_other_vote_received.load(std::memory_order_relaxed))("bt", _accepted_block_time));
_pending_block_mode = pending_block_mode::speculating;
not_producing_when_time = true;
} else if (_max_reversible_blocks > 0 && head_block_num - head.irreversible_blocknum() > _max_reversible_blocks) {
fc_elog(_log, "Not producing block because max-reversible-blocks ${m} reached, head ${h}, lib ${l}.",
("m", _max_reversible_blocks)("h", head_block_num)("l", head.irreversible_blocknum()));
_pending_block_mode = pending_block_mode::speculating;
not_producing_when_time = true;
}

// !not_producing_when_time to avoid tight spin because of error or paused production
Expand Down
4 changes: 0 additions & 4 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -244,10 +244,6 @@ add_test(NAME terminate-scenarios-if-test-replay-pass-transition COMMAND tests/t
set_property(TEST terminate-scenarios-if-test-replay-pass-transition PROPERTY LABELS nonparallelizable_tests)
add_test(NAME terminate-scenarios-if-test-hard_replay-pass-transition COMMAND tests/terminate-scenarios-test.py -c hardReplay --terminate-at-block 150 --kill-sig term --activate-if ${UNSHARE} WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
set_property(TEST terminate-scenarios-if-test-hard_replay-pass-transition PROPERTY LABELS nonparallelizable_tests)
add_test(NAME terminate-scenarios-if-test-max-reversible-blocks-sync COMMAND tests/terminate-scenarios-test.py -c resync --max-reversible-blocks 25 --kill-sig term --activate-if ${UNSHARE} WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
set_property(TEST terminate-scenarios-if-test-max-reversible-blocks-sync PROPERTY LABELS nonparallelizable_tests)
add_test(NAME terminate-scenarios-if-test-max-reversible-blocks-replay COMMAND tests/terminate-scenarios-test.py -c replay --max-reversible-blocks 25 --kill-sig term --activate-if ${UNSHARE} WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
set_property(TEST terminate-scenarios-if-test-max-reversible-blocks-replay PROPERTY LABELS nonparallelizable_tests)
add_test(NAME validate_dirty_db_test COMMAND tests/validate-dirty-db.py -v ${UNSHARE} WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
set_property(TEST validate_dirty_db_test PROPERTY LABELS nonparallelizable_tests)
add_test(NAME keosd_auto_launch_test COMMAND tests/keosd_auto_launch_test.py WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
Expand Down
2 changes: 0 additions & 2 deletions tests/nodeos_startup_catchup.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,6 @@
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,
Expand Down
19 changes: 1 addition & 18 deletions tests/terminate-scenarios-test.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,13 @@
# (--delete-all-blocks), "hardReplay"(--hard-replay-blockchain), and "none" to indicate what kind of restart flag should
# be used. This is one of the only test that actually verify that nodeos terminates with a good exit status.
#
# Also used to test max-reversible-blocks in savanna.
#
###############################################################


Print=Utils.Print
errorExit=Utils.errorExit

appArgs=AppArgs()
appArgs.add(flag="--max-reversible-blocks", type=int, help="pass max-reversible-blocks to nodeos", default=0)

args=TestHelper.parse_args({"-d","-c","--kill-sig","--keep-logs"
,"--activate-if","--dump-error-details","-v","--leave-running"
,"--terminate-at-block","--unshared"}, applicationSpecificArgs=appArgs)
Expand All @@ -37,7 +33,6 @@
activateIF=args.activate_if
dumpErrorDetails=args.dump_error_details
terminate=args.terminate_at_block
maxReversibleBlocks=args.max_reversible_blocks

seed=1
Utils.Debug=debug
Expand All @@ -49,11 +44,6 @@

try:
TestHelper.printSystemInfo("BEGIN")
if maxReversibleBlocks > 0 and not activateIF:
errorExit("--max-reversible-blocks requires --activate-if")
if maxReversibleBlocks > 0 and terminate > 0:
errorExit("Test supports only one of --max-reversible-blocks requires --terminate-at-block")

cluster.setWalletMgr(walletMgr)
cluster.setChainStrategy(chainSyncStrategyStr)

Expand All @@ -64,11 +54,6 @@
if cluster.launch(pnodes=pnodes, totalNodes=total_nodes, totalProducers=pnodes, topo=topo, delay=delay, activateIF=activateIF) is False:
errorExit("Failed to stand up eos cluster.")

# killing bios node means LIB will not advance as it hosts the only finalizer
if maxReversibleBlocks > 0:
Print ("Kill bios node")
cluster.biosNode.kill(signal.SIGTERM)

Print ("Wait for Cluster stabilization")
# wait for cluster to start producing blocks
if not cluster.waitOnClusterBlockNumSync(3):
Expand All @@ -88,13 +73,11 @@

Print ("Relaunch dead cluster node instance.")
nodeArg = "--terminate-at-block %d" % terminate if terminate > 0 else ""
if nodeArg == "":
nodeArg = "--max-reversible-blocks %d --production-pause-vote-timeout-ms 0" % maxReversibleBlocks if maxReversibleBlocks > 0 else ""
if nodeArg != "":
if chainSyncStrategyStr == "hardReplay":
nodeArg += " --truncate-at-block %d" % terminate
nodeArg += " --enable-stale-production "
if cluster.relaunchEosInstances(nodeArgs=nodeArg, waitForTerm=(terminate > 0 or maxReversibleBlocks > 0)) is False:
if cluster.relaunchEosInstances(nodeArgs=nodeArg, waitForTerm=(terminate > 0)) is False:
errorExit("Failed to relaunch Eos instance")
Print("nodeos instance relaunched.")

Expand Down

0 comments on commit fdb4e46

Please sign in to comment.