Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/GH-2125-forkdb-simpler' into GH-…
Browse files Browse the repository at this point in the history
…2159-late-blocks
  • Loading branch information
heifner committed Mar 1, 2024
2 parents 7aae8f0 + 2a2a5da commit e02311f
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 72 deletions.
23 changes: 12 additions & 11 deletions libraries/chain/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1023,15 +1023,15 @@ struct controller_impl {
});
}

signed_block_ptr fork_db_fetch_block_by_num(uint32_t block_num) const {
signed_block_ptr fetch_block_on_head_branch_by_num(uint32_t block_num) const {
return fork_db.apply<signed_block_ptr>([&](const auto& forkdb) {
auto bsp = forkdb.search_on_head_branch(block_num);
if (bsp) return bsp->block;
return signed_block_ptr{};
});
}

std::optional<block_id_type> fork_db_fetch_block_id_by_num(uint32_t block_num) const {
std::optional<block_id_type> fetch_block_id_on_head_branch_by_num(uint32_t block_num) const {
return fork_db.apply<std::optional<block_id_type>>([&](const auto& forkdb) -> std::optional<block_id_type> {
auto bsp = forkdb.search_on_head_branch(block_num);
if (bsp) return bsp->id();
Expand All @@ -1040,7 +1040,7 @@ struct controller_impl {
}

// search on the branch of head
block_state_ptr fork_db_fetch_bsp_by_num(uint32_t block_num) const {
block_state_ptr fetch_bsp_on_head_branch_by_num(uint32_t block_num) const {
return fork_db.apply<block_state_ptr>(
overloaded{
[](const fork_database_legacy_t&) -> block_state_ptr { return nullptr; },
Expand All @@ -1053,7 +1053,7 @@ struct controller_impl {
}

// search on the branch of given id
block_state_ptr fork_db_fetch_bsp_by_num(const block_id_type& id, uint32_t block_num) const {
block_state_ptr fetch_bsp_on_branch_by_num(const block_id_type& id, uint32_t block_num) const {
return fork_db.apply<block_state_ptr>(
overloaded{
[](const fork_database_legacy_t&) -> block_state_ptr { return nullptr; },
Expand Down Expand Up @@ -2813,7 +2813,8 @@ struct controller_impl {
assert(bsp->header_exts.count(if_ext_id) > 0); // in all instant_finality block headers
const auto& if_ext = std::get<instant_finality_extension>(bsp->header_exts.lower_bound(if_ext_id)->second);
if (if_ext.qc_claim.is_strong_qc) {
auto claimed = forkdb.search_on_head_branch(if_ext.qc_claim.block_num);
// claim has already been verified
auto claimed = forkdb.search_on_branch(bsp->id(), if_ext.qc_claim.block_num);
if (claimed) {
set_if_irreversible_block_num(claimed->core.final_on_strong_qc_block_num);
}
Expand Down Expand Up @@ -3177,7 +3178,7 @@ struct controller_impl {
const auto& qc_ext = std::get<quorum_certificate_extension>(block_exts.lower_bound(qc_ext_id)->second);
const auto& received_qc = qc_ext.qc.qc;

const auto bsp = fork_db_fetch_bsp_by_num( bsp_in->previous(), qc_ext.qc.block_num );
const auto bsp = fetch_bsp_on_branch_by_num( bsp_in->previous(), qc_ext.qc.block_num );
if( !bsp ) {
return;
}
Expand Down Expand Up @@ -3307,7 +3308,7 @@ struct controller_impl {
("s1", qc_proof.qc.is_strong())("s2", new_qc_claim.is_strong_qc)("b", block_num) );

// find the claimed block's block state on branch of id
auto bsp = fork_db_fetch_bsp_by_num( prev.id(), new_qc_claim.block_num );
auto bsp = fetch_bsp_on_branch_by_num( prev.id(), new_qc_claim.block_num );
EOS_ASSERT( bsp,
invalid_qc_claim,
"Block state was not found in forkdb for block_num ${q}. Block number: ${b}",
Expand Down Expand Up @@ -3570,7 +3571,7 @@ struct controller_impl {
} else if( new_head->id() != head->id() ) {
ilog("switching forks from ${current_head_id} (block number ${current_head_num}) ${c} to ${new_head_id} (block number ${new_head_num}) ${n}",
("current_head_id", head->id())("current_head_num", head_block_num())("new_head_id", new_head->id())("new_head_num", new_head->block_num())
("c", fork_comparison{*head})("n", fork_comparison{*new_head}));
("c", log_fork_comparison(*head))("n", log_fork_comparison(*new_head)));

// not possible to log transaction specific infor when switching forks
if (auto dm_logger = get_deep_mind_logger(false)) {
Expand Down Expand Up @@ -4540,15 +4541,15 @@ std::optional<signed_block_header> controller::fetch_block_header_by_id( const b
}

signed_block_ptr controller::fetch_block_by_number( uint32_t block_num )const { try {
auto b = my->fork_db_fetch_block_by_num( block_num );
auto b = my->fetch_block_on_head_branch_by_num( block_num );
if (b)
return b;

return my->blog.read_block_by_num(block_num);
} FC_CAPTURE_AND_RETHROW( (block_num) ) }

std::optional<signed_block_header> controller::fetch_block_header_by_number( uint32_t block_num )const { try {
auto b = my->fork_db_fetch_block_by_num(block_num);
auto b = my->fetch_block_on_head_branch_by_num(block_num);
if (b)
return *b;

Expand All @@ -4562,7 +4563,7 @@ block_id_type controller::get_block_id_for_num( uint32_t block_num )const { try
bool find_in_blog = (blog_head && block_num <= blog_head->block_num());

if( !find_in_blog ) {
std::optional<block_id_type> id = my->fork_db_fetch_block_id_by_num(block_num);
std::optional<block_id_type> id = my->fetch_block_id_on_head_branch_by_num(block_num);
if (id) return *id;
}

Expand Down
105 changes: 56 additions & 49 deletions libraries/chain/fork_database.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,44 +23,43 @@ namespace eosio::chain {
struct block_state_accessor {
static bool is_valid(const block_state& bs) { return bs.is_valid(); }
static void set_valid(block_state& bs, bool v) { bs.validated = v; }
static uint32_t last_final_block_num(const block_state& bs) { return bs.core.last_final_block_num(); }
static uint32_t lastest_qc_claim_block_num(const block_state& bs) { return bs.core.latest_qc_claim().block_num; }
static uint32_t block_height(const block_state& bs) { return bs.timestamp().slot; }
};

struct block_state_legacy_accessor {
static bool is_valid(const block_state_legacy& bs) { return bs.is_valid(); }
static void set_valid(block_state_legacy& bs, bool v) { bs.validated = v; }
static uint32_t last_final_block_num(const block_state_legacy& bs) { return bs.irreversible_blocknum(); }
static uint32_t lastest_qc_claim_block_num(const block_state_legacy& bs) { return bs.irreversible_blocknum(); }
static uint32_t block_height(const block_state_legacy& bs) { return bs.block_num(); }
};

template <typename BS>
fork_comparison<BS>::fork_comparison(const BS& bs)
: valid(BS::fork_db_block_state_accessor_t::is_valid(bs))
, last_final_block_num(BS::fork_db_block_state_accessor_t::last_final_block_num(bs))
, lastest_qc_claim_block_num(BS::fork_db_block_state_accessor_t::lastest_qc_claim_block_num(bs))
, block_height(BS::fork_db_block_state_accessor_t::block_height(bs))
{}
std::string log_fork_comparison(const block_state& bs) {
std::string r;
r += "[ valid: " + std::to_string(block_state_accessor::is_valid(bs)) + ", ";
r += "last_final_block_num: " + std::to_string(bs.last_final_block_num()) + ", ";
r += "last_qc_block_num: " + std::to_string(bs.last_qc_block_num()) + ", ";
r += "timestamp: " + bs.timestamp().to_time_point().to_iso_string() + " ]";
return r;
}

std::string log_fork_comparison(const block_state_legacy& bs) {
std::string r;
r += "[ valid: " + std::to_string(block_state_legacy_accessor::is_valid(bs)) + ", ";
r += "irreversible_blocknum: " + std::to_string(bs.irreversible_blocknum()) + ", ";
r += "block_num: " + std::to_string(bs.block_num()) + ", ";
r += "timestamp: " + bs.timestamp().to_time_point().to_iso_string() + " ]";
return r;
}

struct by_block_id;
struct by_best_branch;
struct by_prev;

template<class BS, class BSP>
void log_bs(const char* desc, fork_database_impl<BSP>& fork_db, const BS& lhs) {
using BSA = BS::fork_db_block_state_accessor_t;
dlog( "fork_db ${f}, ${d} ${bn}, last_final_block_num ${lfbn}, final_on_strong_qc_block_num ${fsbn}, lastest_qc_claim_block_num ${lbn}, block_height ${bh}, id ${id}",
("f", (uint64_t)(&fork_db))("d", desc)("bn", lhs.block_num())("lfbn", BSA::last_final_block_num(lhs))("fsbn", BSA::final_on_strong_qc_block_num(lhs))("lbn", BSA::lastest_qc_claim_block_num(lhs))("bh", BSA::block_height(lhs))("id", lhs.id()) );
}

// match comparison of by_best_branch
template<class BS>
bool first_preferred( const BS& lhs, const BS& rhs ) {
using BSA = BS::fork_db_block_state_accessor_t;
return std::make_tuple(BSA::last_final_block_num(lhs), BSA::lastest_qc_claim_block_num(lhs), BSA::block_height(lhs)) >
std::make_tuple(BSA::last_final_block_num(rhs), BSA::lastest_qc_claim_block_num(rhs), BSA::block_height(rhs));
bool first_preferred( const block_state& lhs, const block_state& rhs ) {
return std::make_tuple(lhs.last_final_block_num(), lhs.last_qc_block_num(), lhs.timestamp()) >
std::make_tuple(rhs.last_final_block_num(), rhs.last_qc_block_num(), rhs.timestamp());
}
bool first_preferred( const block_state_legacy& lhs, const block_state_legacy& rhs ) {
return std::make_tuple(lhs.irreversible_blocknum(), lhs.block_num()) >
std::make_tuple(rhs.irreversible_blocknum(), rhs.block_num());
}

template<class BSP> // either [block_state_legacy_ptr, block_state_ptr], same with block_header_state_ptr
Expand All @@ -76,24 +75,40 @@ namespace eosio::chain {
using full_branch_t = fork_db_t::full_branch_t;
using branch_pair_t = fork_db_t::branch_pair_t;

using by_best_branch_legacy_t =
ordered_unique<tag<by_best_branch>,
composite_key<block_state_legacy,
global_fun<const block_state_legacy&, bool, &block_state_legacy_accessor::is_valid>,
const_mem_fun<block_state_legacy, uint32_t, &block_state_legacy::irreversible_blocknum>,
const_mem_fun<block_state_legacy, uint32_t, &block_state_legacy::block_num>,
const_mem_fun<block_state_legacy, const block_id_type&, &block_state_legacy::id>
>,
composite_key_compare<std::greater<bool>, std::greater<uint32_t>, std::greater<uint32_t>, sha256_less
>>;

using by_best_branch_if_t =
ordered_unique<tag<by_best_branch>,
composite_key<block_state,
global_fun<const block_state&, bool, &block_state_accessor::is_valid>,
const_mem_fun<block_state, uint32_t, &block_state::last_final_block_num>,
const_mem_fun<block_state, uint32_t, &block_state::last_qc_block_num>,
const_mem_fun<block_state, block_timestamp_type, &block_state::timestamp>,
const_mem_fun<block_state, const block_id_type&, &block_state::id>
>,
composite_key_compare<std::greater<bool>, std::greater<uint32_t>, std::greater<uint32_t>,
std::greater<block_timestamp_type>, sha256_less>
>;

using by_best_branch_t = std::conditional_t<std::is_same_v<bs_t, block_state>,
by_best_branch_if_t,
by_best_branch_legacy_t>;

using fork_multi_index_type = multi_index_container<
bsp_t,
indexed_by<
hashed_unique<tag<by_block_id>, BOOST_MULTI_INDEX_CONST_MEM_FUN(bs_t, const block_id_type&, id), std::hash<block_id_type>>,
ordered_non_unique<tag<by_prev>, const_mem_fun<bs_t, const block_id_type&, &bs_t::previous>>,
ordered_unique<tag<by_best_branch>,
composite_key<bs_t,
global_fun<const bs_t&, bool, &bs_accessor_t::is_valid>,
global_fun<const bs_t&, uint32_t, &bs_accessor_t::last_final_block_num>,
global_fun<const bs_t&, uint32_t, &bs_accessor_t::lastest_qc_claim_block_num>,
global_fun<const bs_t&, uint32_t, &bs_accessor_t::block_height>,
const_mem_fun<bs_t, const block_id_type&, &bs_t::id>
>,
composite_key_compare<std::greater<bool>,
std::greater<uint32_t>, std::greater<uint32_t>, std::greater<uint32_t>,
sha256_less
>
>
by_best_branch_t
>
>;

Expand Down Expand Up @@ -534,12 +549,7 @@ namespace eosio::chain {

template<class BSP>
BSP fork_database_impl<BSP>::search_on_head_branch_impl( uint32_t block_num ) const {
for (auto i = index.find(head->id()); i != index.end(); i = index.find((*i)->previous())) {
if ((*i)->block_num() == block_num)
return *i;
}

return {};
return search_on_branch_impl(head->id(), block_num);
}

/**
Expand Down Expand Up @@ -643,13 +653,13 @@ namespace eosio::chain {
}

template<class BSP>
void fork_database_t<BSP>::mark_valid( const BSP& h ) {
void fork_database_t<BSP>::mark_valid( const bsp_t& h ) {
std::lock_guard g( my->mtx );
my->mark_valid_impl( h );
}

template<class BSP>
void fork_database_impl<BSP>::mark_valid_impl( const BSP& h ) {
void fork_database_impl<BSP>::mark_valid_impl( const bsp_t& h ) {
if( bs_accessor_t::is_valid(*h) ) return;

auto& by_id_idx = index.template get<by_block_id>();
Expand Down Expand Up @@ -772,9 +782,6 @@ namespace eosio::chain {
}

// do class instantiations
template struct fork_comparison<block_state_legacy>;
template struct fork_comparison<block_state>;

template class fork_database_t<block_state_legacy_ptr>;
template class fork_database_t<block_state_ptr>;

Expand Down
3 changes: 2 additions & 1 deletion libraries/chain/include/eosio/chain/block_state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ struct block_state : public block_header_state { // block_header_state provi
uint32_t block_num() const { return block_header_state::block_num(); }
block_timestamp_type timestamp() const { return block_header_state::timestamp(); }
const extensions_type& header_extensions() const { return block_header_state::header.header_extensions; }
uint32_t irreversible_blocknum() const { return core.last_final_block_num(); }
uint32_t irreversible_blocknum() const { return core.last_final_block_num(); } // backwards compatibility
uint32_t last_final_block_num() const { return core.last_final_block_num(); }
std::optional<quorum_certificate> get_best_qc() const;
uint32_t last_qc_block_num() const { return core.latest_qc_claim().block_num; }
uint32_t final_on_strong_qc_block_num() const { return core.final_on_strong_qc_block_num; }
Expand Down
14 changes: 3 additions & 11 deletions libraries/chain/include/eosio/chain/fork_database.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,16 @@

namespace eosio::chain {

template<class bsp>
template<class BSP>
struct fork_database_impl;

using block_branch_t = std::vector<signed_block_ptr>;
enum class mark_valid_t { no, yes };
enum class ignore_duplicate_t { no, yes };

// Used for logging of comparison values used for best fork determination
template<typename BS>
struct fork_comparison {
explicit fork_comparison(const BS& bs);
const bool valid;
const uint32_t last_final_block_num{};
const uint32_t lastest_qc_claim_block_num{};
const uint32_t block_height{};
};
std::string log_fork_comparison(const block_state& bs);
std::string log_fork_comparison(const block_state_legacy& bs);

/**
* @class fork_database_t
Expand Down Expand Up @@ -252,5 +246,3 @@ namespace eosio::chain {
static constexpr uint32_t max_supported_version = 1;
};
} /// eosio::chain

FC_REFLECT_TEMPLATE((typename BS), eosio::chain::fork_comparison<BS>, (valid)(last_final_block_num)(lastest_qc_claim_block_num)(block_height))
15 changes: 15 additions & 0 deletions unittests/fork_db_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,21 @@ BOOST_AUTO_TEST_CASE(add_remove_test) try {
forkdb.add(bsp13b, mark_valid_t::no, ignore_duplicate_t::no); // will throw if already exists
forkdb.add(bsp14b, mark_valid_t::no, ignore_duplicate_t::no); // will throw if already exists

// test search
BOOST_TEST(forkdb.search_on_branch( bsp13bb->id(), 11) == bsp11b);
BOOST_TEST(forkdb.search_on_branch( bsp13bb->id(), 9) == block_state_ptr{});

// test fetch branch
auto branch = forkdb.fetch_branch( bsp13b->id(), 12);
BOOST_REQUIRE(branch.size() == 2);
BOOST_TEST(branch[0] == bsp12b);
BOOST_TEST(branch[1] == bsp11b);
branch = forkdb.fetch_branch( bsp13bbb->id(), 13);
BOOST_REQUIRE(branch.size() == 3);
BOOST_TEST(branch[0] == bsp13bbb);
BOOST_TEST(branch[1] == bsp12bb);
BOOST_TEST(branch[2] == bsp11b);

} FC_LOG_AND_RETHROW();

BOOST_AUTO_TEST_SUITE_END()

0 comments on commit e02311f

Please sign in to comment.