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

IF: Do not advance LIB past HEAD #52

Merged
merged 3 commits into from
Apr 18, 2024
Merged
Show file tree
Hide file tree
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
11 changes: 6 additions & 5 deletions libraries/chain/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1398,17 +1398,18 @@ struct controller_impl {
("lib_num", lib_num)("bn", fork_db_root_block_num()) );
}

block_id_type irreversible_block_id = if_irreversible_block_id.load();
uint32_t if_lib_num = block_header::num_from_id(irreversible_block_id);
const uint32_t new_lib_num = if_lib_num > 0 ? if_lib_num : fork_db_head_irreversible_blocknum();
const block_id_type irreversible_block_id = if_irreversible_block_id.load();
const uint32_t savanna_lib_num = block_header::num_from_id(irreversible_block_id);
const bool savanna = savanna_lib_num > 0;
const uint32_t new_lib_num = savanna ? savanna_lib_num : fork_db_head_irreversible_blocknum();

if( new_lib_num <= lib_num )
return;

bool savanna_transistion_required = false;
auto mark_branch_irreversible = [&, this](auto& forkdb) {
auto branch = (if_lib_num > 0) ? forkdb.fetch_branch( irreversible_block_id, new_lib_num)
: forkdb.fetch_branch( fork_db_head_or_pending(forkdb)->id(), new_lib_num );
auto branch = savanna ? forkdb.fetch_branch( fork_db_head_or_pending(forkdb)->id(), irreversible_block_id)
: forkdb.fetch_branch( fork_db_head_or_pending(forkdb)->id(), new_lib_num );
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
Expand Down
25 changes: 24 additions & 1 deletion libraries/chain/fork_database.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ namespace eosio::chain {
void remove_impl( const block_id_type& id );
branch_t fetch_branch_impl( const block_id_type& h, uint32_t trim_after_block_num ) const;
block_branch_t fetch_block_branch_impl( const block_id_type& h, uint32_t trim_after_block_num ) const;
branch_t fetch_branch_impl( const block_id_type& h, const block_id_type& b ) const;
full_branch_t fetch_full_branch_impl(const block_id_type& h) const;
bsp_t search_on_branch_impl( const block_id_type& h, uint32_t block_num, include_root_t include_root ) const;
bsp_t search_on_head_branch_impl( uint32_t block_num, include_root_t include_root ) const;
Expand Down Expand Up @@ -438,6 +439,28 @@ namespace eosio::chain {
return result;
}

template <class BSP>
fork_database_t<BSP>::branch_t
fork_database_t<BSP>::fetch_branch(const block_id_type& h, const block_id_type& b) const {
std::lock_guard g(my->mtx);
return my->fetch_branch_impl(h, b);
}

template <class BSP>
fork_database_t<BSP>::branch_t
fork_database_impl<BSP>::fetch_branch_impl(const block_id_type& h, const block_id_type& b) const {
branch_t result;
result.reserve(index.size());
bool found_branch = false;
for (auto i = index.find(h); i != index.end(); i = index.find((*i)->previous())) {
if ((*i)->id() == b)
found_branch = true;
if (found_branch)
result.push_back(*i);
}
return result;
}

template <class BSP>
block_branch_t
fork_database_t<BSP>::fetch_block_branch(const block_id_type& h, uint32_t trim_after_block_num) const {
Expand Down Expand Up @@ -594,7 +617,7 @@ namespace eosio::chain {

for( uint32_t i = 0; i < remove_queue.size(); ++i ) {
EOS_ASSERT( remove_queue[i] != head_id, fork_database_exception,
"removing the block and its descendants would remove the current head block" );
"removing the block and its descendants would remove the current head block ${id}", ("id", head_id) );

auto previtr = previdx.lower_bound( remove_queue[i] );
while( previtr != previdx.end() && (*previtr)->previous() == remove_queue[i] ) {
Expand Down
7 changes: 7 additions & 0 deletions libraries/chain/include/eosio/chain/fork_database.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,13 @@ namespace eosio::chain {
branch_t fetch_branch( const block_id_type& h, uint32_t trim_after_block_num = std::numeric_limits<uint32_t>::max() ) const;
block_branch_t fetch_block_branch( const block_id_type& h, uint32_t trim_after_block_num = std::numeric_limits<uint32_t>::max() ) const;

/**
* Returns the sequence of block states resulting from trimming the branch from the
* root block (exclusive) to the block with an id of `h` (inclusive) by removing any
* block states that are after block `b`. Returns empty if `b` not found on `h` branch.
*/
branch_t fetch_branch( const block_id_type& h, const block_id_type& b ) const;

/**
* Returns full branch of block_header_state pointers including the root.
* The order of the sequence is in descending block number order.
Expand Down
11 changes: 11 additions & 0 deletions unittests/fork_db_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,17 @@ BOOST_AUTO_TEST_CASE(add_remove_test) try {
BOOST_TEST(branch[1] == bsp12bb);
BOOST_TEST(branch[2] == bsp11b);

// test fetch branch providing head and lib
BOOST_TEST(forkdb.head()->id() == root->id());
forkdb.mark_valid(bsp13a);
BOOST_TEST(forkdb.head()->id() == bsp13a->id());
branch = forkdb.fetch_branch(forkdb.head()->id(), bsp11c->id());
BOOST_TEST(branch.empty()); // bsp11c not on bsp13a branch
branch = forkdb.fetch_branch(forkdb.head()->id(), bsp12a->id());
BOOST_REQUIRE(branch.size() == 2);
BOOST_TEST(branch[0] == bsp12a);
BOOST_TEST(branch[1] == bsp11a);

} FC_LOG_AND_RETHROW();

BOOST_AUTO_TEST_SUITE_END()
Loading