Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Irreversible mode improvements #1086

Merged
merged 3 commits into from
Dec 21, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 25 additions & 17 deletions libraries/chain/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1498,7 +1498,7 @@ struct controller_impl {
}
}

void log_irreversible() {
controller::apply_blocks_result log_irreversible() {
EOS_ASSERT( fork_db_has_root(), fork_database_exception, "fork database not properly initialized" );

const std::optional<block_id_type> log_head_id = blog.head_id();
Expand Down Expand Up @@ -1538,9 +1538,10 @@ struct controller_impl {

const block_id_type new_lib_id = pending_lib_id();
const block_num_type new_lib_num = block_header::num_from_id(new_lib_id);
controller::apply_blocks_result result = controller::apply_blocks_result::complete;

if( new_lib_num <= lib_num )
return;
return result;

const fc::time_point start = fc::time_point::now();

Expand All @@ -1555,22 +1556,15 @@ struct controller_impl {
// pending LIB. If the pending LIB not found on the head branch then fetch_branch returns an empty branch.
// Otherwise fetch_branch will return from chain_head to root iff chain_head on pending LIB branch.
auto branch = new_lib_num <= head_num ? fork_db.fetch_branch(head_id, new_lib_id) : fork_db.fetch_branch(new_lib_id, head_id);
try {
try { try {
auto should_process = [&](auto& bsp) {
// Only make irreversible blocks that have been validated. Blocks in the fork database may not be on our current best head
// and therefore have not been validated.
// An alternative more complex implementation would be to do a fork switch here and validate all blocks so they can be then made
// irreversible. Instead, this moves irreversible as much as possible and allows the next maybe_switch_forks call to apply these
// non-validated blocks. After the maybe_switch_forks call (before next produced block or on next received block), irreversible
// can then move forward on the then validated blocks.
// In irreversible mode, break every ~500ms to allow other tasks (e.g. get_info, SHiP) opportunity to run. There is a post
// for every incoming blocks; enough posted tasks to apply all blocks queued to the fork db.
if (irreversible_mode()) {
if (!replaying && fc::time_point::now() - start > fc::milliseconds(500))
greg7mdp marked this conversation as resolved.
Show resolved Hide resolved
return false;
return true;
}
return bsp->is_valid();
return irreversible_mode() || bsp->is_valid();
};

using packed_block_future = std::future<std::vector<char>>;
Expand All @@ -1587,7 +1581,8 @@ struct controller_impl {
packed_block_future f;
if (irreversible_mode()) {
f = post_async_task( thread_pool.get_executor(), [b=(*bitr)->block]() { return fc::raw::pack(*b); } );
if (apply_irreversible_block(fork_db, *bitr) != controller::apply_blocks_result::complete)
result = apply_irreversible_block(fork_db, *bitr);
if (result != controller::apply_blocks_result::complete)
break;
}

Expand All @@ -1604,10 +1599,19 @@ struct controller_impl {
fork_db_.switch_to(fork_database::in_use_t::savanna);
break;
}
if (irreversible_mode()) {
// In irreversible mode, break every ~500ms to allow other tasks (e.g. get_info, SHiP) opportunity to run
const bool more_blocks_to_process = bitr + 1 != branch.rend();
if (!replaying && more_blocks_to_process && fc::time_point::now() - start > fc::milliseconds(500)) {
result = controller::apply_blocks_result::incomplete;
break;
}
}
}
} catch( const std::exception& e ) {
} FC_CAPTURE_AND_RETHROW() } catch ( const fc::exception& e ) {
try {
elog("Caught exception while logging irreversible: ${e}", ("e", e.what()));
if (e.code() != interrupt_exception::code_value)
elog("Caught exception while logging irreversible: ${e}", ("e", e.to_detail_string()));
if (root_id != fork_db.root()->id()) {
fork_db.advance_root(root_id);
}
Expand All @@ -1631,6 +1635,8 @@ struct controller_impl {
};

fork_db_.apply<void>(mark_branch_irreversible);

return result;
}

void initialize_blockchain_state(const genesis_state& genesis) {
Expand Down Expand Up @@ -4357,9 +4363,9 @@ struct controller_impl {
return maybe_apply_blocks( cb, trx_lookup );
}

log_irreversible();
auto result = log_irreversible();
transition_to_savanna_if_needed();
return should_pause() ? controller::apply_blocks_result::paused : controller::apply_blocks_result::complete;
return result;
} catch (fc::exception& e) {
if (e.code() != interrupt_exception::code_value) {
wlog("${d}", ("d",e.to_detail_string()));
Expand Down Expand Up @@ -4500,8 +4506,10 @@ struct controller_impl {
}

// irreversible can change even if block not applied to head, integrated qc can move LIB
log_irreversible();
auto log_result = log_irreversible();
transition_to_savanna_if_needed();
if (log_result != controller::apply_blocks_result::complete)
result = log_result;
};

fork_db_.apply<void>(do_apply_blocks);
Expand Down
Loading