From de976705ee706e767a094894f37ba96b3ac6260f Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Mon, 4 Mar 2024 11:36:56 -0600 Subject: [PATCH 1/2] GH-2141 Move chain_head from fork database back to controller --- libraries/chain/controller.cpp | 376 +++++++++--------- libraries/chain/fork_database.cpp | 19 +- .../include/eosio/chain/block_handle.hpp | 33 ++ .../chain/include/eosio/chain/controller.hpp | 12 +- .../include/eosio/chain/fork_database.hpp | 35 +- 5 files changed, 256 insertions(+), 219 deletions(-) create mode 100644 libraries/chain/include/eosio/chain/block_handle.hpp diff --git a/libraries/chain/controller.cpp b/libraries/chain/controller.cpp index 0ff23872a9..0c3664f460 100644 --- a/libraries/chain/controller.cpp +++ b/libraries/chain/controller.cpp @@ -125,6 +125,26 @@ struct qc_data_t { // and specify `weak`. }; +template +R apply_savanna(const block_handle& bh, F&& f) { + if constexpr (std::is_same_v) + std::visit(overloaded{[&](const block_state_legacy_ptr&) {}, + [&](const block_state_ptr& head) { std::forward(f)(head); }}, bh.internal()); + else + return std::visit(overloaded{[&](const block_state_legacy_ptr&) -> R { return {}; }, + [&](const block_state_ptr& head) -> R { return std::forward(f)(head); }}, bh.internal()); +} + +template +R apply_legacy(const block_handle& bh, F&& f) { + if constexpr (std::is_same_v) + std::visit(overloaded{[&](const block_state_legacy_ptr& head) { std::forward(f)(head); }, + [&](const block_state_ptr&) {}}, bh.internal()); + else + return std::visit(overloaded{[&](const block_state_legacy_ptr& head) -> R { return std::forward(f)(head); }, + [&](const block_state_ptr&) -> R { return {}; }}, bh.internal()); +} + struct completed_block { std::variant bsp; @@ -656,7 +676,7 @@ struct building_block { // we are simulating a block received from the network. Use the embedded qc from the block qc_data = std::move(validating_qc_data); } else { - fork_db.apply_if([&](const auto& forkdb) { + fork_db.apply_savanna([&](const auto& forkdb) { auto branch = forkdb.fetch_branch(parent_id()); std::optional qc; for( auto it = branch.begin(); it != branch.end(); ++it ) { @@ -815,6 +835,7 @@ struct controller_impl { chainbase::database db; block_log blog; std::optional pending; + block_handle chain_head; fork_database fork_db; block_id_type if_irreversible_block_id; resource_limits_manager resource_limits; @@ -858,72 +879,48 @@ struct controller_impl { int64_t set_proposed_producers( vector producers ); int64_t set_proposed_producers_legacy( vector producers ); - uint32_t head_block_num() const { - return fork_db.apply([](const auto& forkdb) { return forkdb.chain_head->block_num(); }); - } - block_timestamp_type head_block_time() const { - return fork_db.apply([](const auto& forkdb) { return forkdb.chain_head->timestamp(); }); - } - account_name head_block_producer() const { - return fork_db.apply([](const auto& forkdb) { return forkdb.chain_head->producer(); }); - } - const block_id_type& head_block_id() const { - return fork_db.apply( - [](const auto& forkdb) -> const block_id_type& { return forkdb.chain_head->id(); }); - } - const block_header& head_block_header() const { - return fork_db.apply( - [](const auto& forkdb) -> const block_header& { return forkdb.chain_head->header; }); - } - const signed_block_ptr& head_block() const { - return fork_db.apply( - [](const auto& forkdb) -> const signed_block_ptr& { return forkdb.chain_head->block; }); - } - protocol_feature_activation_set_ptr head_activated_protocol_features() const { - return fork_db.apply([](const auto& forkdb) { - return forkdb.chain_head->get_activated_protocol_features(); - }); + return std::visit([](const auto& bsp) { + return bsp->get_activated_protocol_features(); + }, chain_head.internal()); } const producer_authority_schedule& head_active_schedule_auth() const { - return fork_db.apply([](const auto& forkdb) -> const producer_authority_schedule& { - return forkdb.chain_head->active_schedule_auth(); - }); + return std::visit([](const auto& bsp) -> const producer_authority_schedule& { + return bsp->active_schedule_auth(); + }, chain_head.internal()); } const producer_authority_schedule* head_pending_schedule_auth_legacy() const { - return fork_db.apply(overloaded{ - [](const fork_database_legacy_t& forkdb) -> const producer_authority_schedule* { - return forkdb.chain_head->pending_schedule_auth(); - }, - [](const fork_database_if_t&) -> const producer_authority_schedule* { return nullptr; } - }); + return std::visit( + overloaded{[](const block_state_legacy_ptr& bsp) -> const producer_authority_schedule* { return bsp->pending_schedule_auth(); }, + [](const block_state_ptr&) -> const producer_authority_schedule* { return nullptr; } + }, chain_head.internal()); } const producer_authority_schedule* next_producers() { - return fork_db.apply(overloaded{ - [](const fork_database_legacy_t& forkdb) -> const producer_authority_schedule* { - return forkdb.chain_head->pending_schedule_auth(); + return std::visit(overloaded{ + [](const block_state_legacy_ptr& bsp) -> const producer_authority_schedule* { + return bsp->pending_schedule_auth(); }, - [](const fork_database_if_t& forkdb) -> const producer_authority_schedule* { - return forkdb.chain_head->proposer_policies.empty() + [](const block_state_ptr& bsp) -> const producer_authority_schedule* { + return bsp->proposer_policies.empty() ? nullptr - : &forkdb.chain_head->proposer_policies.begin()->second->proposer_schedule; + : &bsp->proposer_policies.begin()->second->proposer_schedule; } - }); + }, chain_head.internal()); } void replace_producer_keys( const public_key_type& key ) { ilog("Replace producer keys with ${k}", ("k", key)); - fork_db.apply( + std::visit( overloaded{ - [&](const fork_database_legacy_t& forkdb) { - auto version = forkdb.chain_head->pending_schedule.schedule.version; - forkdb.chain_head->pending_schedule = {}; - forkdb.chain_head->pending_schedule.schedule.version = version; - for (auto& prod: forkdb.chain_head->active_schedule.producers ) { + [&](const block_state_legacy_ptr& bsp) { + auto version = bsp->pending_schedule.schedule.version; + bsp->pending_schedule = {}; + bsp->pending_schedule.schedule.version = version; + for (auto& prod: bsp->active_schedule.producers ) { ilog("${n}", ("n", prod.producer_name)); std::visit([&](auto &auth) { auth.threshold = 1; @@ -931,10 +928,10 @@ struct controller_impl { }, prod.authority); } }, - [](const fork_database_if_t&) { + [](const block_state_ptr&) { // TODO IF: add instant-finality implementation, will need to replace finalizers as well } - }); + }, chain_head.internal()); } // --------------- access fork_db head ---------------------------------------------------------------------- @@ -989,33 +986,36 @@ struct controller_impl { // --------------- fork_db APIs ---------------------------------------------------------------------- template uint32_t pop_block(ForkDB& forkdb) { - typename ForkDB::bsp_t prev = forkdb.get_block( forkdb.chain_head->previous() ); + typename ForkDB::bsp_t prev = forkdb.get_block( chain_head.previous() ); if( !prev ) { - EOS_ASSERT( forkdb.root()->id() == forkdb.chain_head->previous(), block_validate_exception, + EOS_ASSERT( forkdb.root()->id() == chain_head.previous(), block_validate_exception, "attempt to pop beyond last irreversible block" ); prev = forkdb.root(); } - EOS_ASSERT( forkdb.chain_head->block, block_validate_exception, + EOS_ASSERT( chain_head.block(), block_validate_exception, "attempting to pop a block that was sparsely loaded from a snapshot"); - forkdb.chain_head = prev; + chain_head = block_handle{prev}; return prev->block_num(); } - void fork_db_reset_root_to_chain_head() { - return fork_db.apply([&](auto& forkdb) { - forkdb.reset_root(*forkdb.chain_head); - }); - } - bool fork_db_block_exists( const block_id_type& id ) const { return fork_db.apply([&](const auto& forkdb) { return forkdb.block_exists(id); }); } + void fork_db_reset_root_to_chain_head() { + fork_db.apply([&](auto& forkdb) { + std::visit([&](const auto& bsp) { + if constexpr (std::is_same_v, std::decay_t>) + forkdb.reset_root(*bsp); + }, chain_head.internal()); + }); + } + signed_block_ptr fork_db_fetch_block_by_id( const block_id_type& id ) const { return fork_db.apply([&](const auto& forkdb) { auto bsp = forkdb.get_block(id); @@ -1196,7 +1196,7 @@ struct controller_impl { if (auto dm_logger = get_deep_mind_logger(false)) { if (trx && is_onblock(*t)) dm_logger->on_onblock(*trx); - dm_logger->on_applied_transaction(head_block_num() + 1, t); + dm_logger->on_applied_transaction(chain_head.block_num() + 1, t); } } @@ -1282,7 +1282,7 @@ struct controller_impl { void initialize_blockchain_state(const genesis_state& genesis) { wlog( "Initializing new blockchain with genesis state" ); - auto init_blockchain = [&genesis](auto& forkdb) { + auto init_blockchain = [&genesis, this](auto&) { producer_authority_schedule initial_schedule = { 0, { producer_authority{config::system_account_name, block_signing_authority_v0{ 1, {{genesis.initial_key, 1}} } } } }; legacy::producer_schedule_type initial_legacy_schedule{ 0, {{config::system_account_name, genesis.initial_key}} }; @@ -1296,15 +1296,16 @@ struct controller_impl { genheader.id = genheader.header.calculate_id(); genheader.block_num = genheader.header.block_num(); - forkdb.chain_head = std::make_shared(); - static_cast(*forkdb.chain_head) = genheader; - forkdb.chain_head->activated_protocol_features = std::make_shared(); - forkdb.chain_head->block = std::make_shared(genheader.header); + auto head = std::make_shared(); + static_cast(*head) = genheader; + head->activated_protocol_features = std::make_shared(); + head->block = std::make_shared(genheader.header); + chain_head = block_handle{head}; }; fork_db.apply_legacy(init_blockchain); // assuming here that genesis_state is always dpos - db.set_revision( head_block_num() ); + db.set_revision( chain_head.block_num() ); initialize_database(genesis); } @@ -1317,19 +1318,18 @@ struct controller_impl { } replaying = true; - auto start_block_num = head_block_num() + 1; + auto start_block_num = chain_head.block_num() + 1; auto start = fc::time_point::now(); std::exception_ptr except_ptr; auto replay_blog = [&](auto& forkdb) { - using BSP = std::decay_t; - auto& head = forkdb.chain_head; + using BSP = std::decay_t; if( blog_head && start_block_num <= blog_head->block_num() ) { ilog( "existing block log, attempting to replay from ${s} to ${n} blocks", ("s", start_block_num)("n", blog_head->block_num()) ); try { - while( auto next = blog.read_block_by_num( head->block_num() + 1 ) ) { + while( auto next = blog.read_block_by_num( chain_head.block_num() + 1 ) ) { replay_push_block( next, controller::block_status::irreversible ); if( check_shutdown() ) break; if( next->block_num() % 500 == 0 ) { @@ -1339,16 +1339,16 @@ struct controller_impl { } catch( const database_guard_exception& e ) { except_ptr = std::current_exception(); } - ilog( "${n} irreversible blocks replayed", ("n", 1 + head->block_num() - start_block_num) ); + ilog( "${n} irreversible blocks replayed", ("n", 1 + chain_head.block_num() - start_block_num) ); auto pending_head = forkdb.pending_head(); if( pending_head ) { ilog( "fork database head ${h}, root ${r}", ("h", pending_head->block_num())( "r", forkdb.root()->block_num() ) ); - if( pending_head->block_num() < head->block_num() || head->block_num() < forkdb.root()->block_num() ) { - ilog( "resetting fork database with new last irreversible block as the new root: ${id}", ("id", head->id()) ); - forkdb.reset_root( *head ); - } else if( head->block_num() != forkdb.root()->block_num() ) { - auto new_root = forkdb.search_on_branch( pending_head->id(), head->block_num() ); + if( pending_head->block_num() < chain_head.block_num() || chain_head.block_num() < forkdb.root()->block_num() ) { + ilog( "resetting fork database with new last irreversible block as the new root: ${id}", ("id", chain_head.id()) ); + fork_db_reset_root_to_chain_head(); + } else if( chain_head.block_num() != forkdb.root()->block_num() ) { + auto new_root = forkdb.search_on_branch( pending_head->id(), chain_head.block_num() ); EOS_ASSERT( new_root, fork_database_exception, "unexpected error: could not find new LIB in fork database" ); ilog( "advancing fork database root to new last irreversible block within existing fork database: ${id}", @@ -1361,16 +1361,16 @@ struct controller_impl { // if the irreverible log is played without undo sessions enabled, we need to sync the // revision ordinal to the appropriate expected value here. if( skip_db_sessions( controller::block_status::irreversible ) ) - db.set_revision( head->block_num() ); + db.set_revision( chain_head.block_num() ); } else { ilog( "no irreversible blocks need to be replayed" ); } if (snapshot_head_block != 0 && !blog_head) { // loading from snapshot without a block log so fork_db can't be considered valid - forkdb.reset_root( *head ); + fork_db_reset_root_to_chain_head(); } else if( !except_ptr && !check_shutdown() && forkdb.head() ) { - auto head_block_num = head->block_num(); + auto head_block_num = chain_head.block_num(); auto branch = fork_db.fetch_branch_from_head(); int rev = 0; for( auto i = branch.rbegin(); i != branch.rend(); ++i ) { @@ -1383,13 +1383,13 @@ struct controller_impl { } if( !forkdb.head() ) { - forkdb.reset_root( *head ); + fork_db_reset_root_to_chain_head(); } auto end = fc::time_point::now(); ilog( "replayed ${n} blocks in ${duration} seconds, ${mspb} ms/block", - ("n", head->block_num() + 1 - start_block_num)("duration", (end-start).count()/1000000) - ("mspb", ((end-start).count()/1000.0)/(head->block_num()-start_block_num)) ); + ("n", chain_head.block_num() + 1 - start_block_num)("duration", (end-start).count()/1000000) + ("mspb", ((end-start).count()/1000.0)/(chain_head.block_num()-start_block_num)) ); replaying = false; }; @@ -1413,12 +1413,12 @@ struct controller_impl { } else { ilog( "Starting initialization from snapshot and no block log, this may take a significant amount of time" ); read_from_snapshot( snapshot, 0, std::numeric_limits::max() ); - EOS_ASSERT( head_block_num() > 0, snapshot_exception, + EOS_ASSERT( chain_head.block_num() > 0, snapshot_exception, "Snapshot indicates controller head at block number 0, but that is not allowed. " "Snapshot is invalid." ); - blog.reset( chain_id, head_block_num() + 1 ); + blog.reset( chain_id, chain_head.block_num() + 1 ); } - ilog( "Snapshot loaded, lib: ${lib}", ("lib", head_block_num()) ); + ilog( "Snapshot loaded, lib: ${lib}", ("lib", chain_head.block_num()) ); init(std::move(check_shutdown)); auto snapshot_load_time = (fc::time_point::now() - snapshot_load_start_time).to_seconds(); @@ -1451,7 +1451,7 @@ struct controller_impl { initialize_blockchain_state(genesis); // sets head to genesis state if( !forkdb.head() ) { - forkdb.reset_root( *forkdb.chain_head ); + fork_db_reset_root_to_chain_head(); } }; @@ -1462,7 +1462,7 @@ struct controller_impl { "block log does not start with genesis block" ); } else { - blog.reset( genesis, head_block() ); + blog.reset( genesis, chain_head.block() ); } init(std::move(check_shutdown)); } @@ -1495,7 +1495,7 @@ struct controller_impl { if( read_mode == db_read_mode::IRREVERSIBLE && forkdb.head()->id() != forkdb.root()->id() ) { forkdb.rollback_head_to_root(); } - forkdb.chain_head = forkdb.head(); + chain_head = block_handle{forkdb.head()}; }; fork_db.apply(do_startup); @@ -1536,16 +1536,16 @@ struct controller_impl { } // At this point head != nullptr - EOS_ASSERT( db.revision() >= head_block_num(), fork_database_exception, + EOS_ASSERT( db.revision() >= chain_head.block_num(), fork_database_exception, "fork database head (${head}) is inconsistent with state (${db})", - ("db",db.revision())("head",head_block_num()) ); + ("db", db.revision())("head", chain_head.block_num()) ); - if( db.revision() > head_block_num() ) { + if( db.revision() > chain_head.block_num() ) { wlog( "database revision (${db}) is greater than head block number (${head}), " "attempting to undo pending changes", - ("db",db.revision())("head",head_block_num()) ); + ("db", db.revision())("head", chain_head.block_num()) ); } - while( db.revision() > head_block_num() ) { + while( db.revision() > chain_head.block_num() ) { db.undo(); } @@ -1553,7 +1553,7 @@ struct controller_impl { // At startup, no transaction specific logging is possible if (auto dm_logger = get_deep_mind_logger(false)) { - dm_logger->on_startup(db, head_block_num()); + dm_logger->on_startup(db, chain_head.block_num()); } if( conf.integrity_hash_on_start ) @@ -1609,7 +1609,7 @@ struct controller_impl { .last_vote = {}, .lock = proposal_ref(lib->id(), lib->timestamp()) }); }; - fork_db.apply_if(set_finalizer_defaults); + fork_db.apply_savanna(set_finalizer_defaults); } else { // we are past the IF transition. auto set_finalizer_defaults = [&](auto& forkdb) -> void { @@ -1619,7 +1619,7 @@ struct controller_impl { .last_vote = {}, .lock = proposal_ref(lib->id(), lib->timestamp()) }); }; - fork_db.apply_if(set_finalizer_defaults); + fork_db.apply_savanna(set_finalizer_defaults); } } } @@ -1708,12 +1708,12 @@ struct controller_impl { }); #warning todo: add snapshot support for new (IF) block_state section - auto write_block_state_section = [&](auto& forkdb) { - snapshot->write_section("eosio::chain::block_state", [&]( auto §ion ) { - section.template add_row(*forkdb.chain_head, db); - }); - }; - fork_db.apply_legacy(write_block_state_section); + std::visit([&](const auto& head) { + if constexpr (std::is_same_v>) + snapshot->write_section("eosio::chain::block_state", [&]( auto& section ) { + section.template add_row(*head, db); + }); + }, chain_head.internal()); controller_index_set::walk_indices([this, &snapshot]( auto utils ){ using value_t = typename decltype(utils)::index_t::value_type; @@ -1787,8 +1787,9 @@ struct controller_impl { ("block_log_last_num", blog_end) ); - forkdb.chain_head = std::make_shared(); - static_cast(*forkdb.chain_head) = head_header_state; + auto head = std::make_shared(); + chain_head = block_handle{head}; + static_cast(*head) = head_header_state; }; fork_db.apply_legacy(read_block_state_section); @@ -1869,7 +1870,7 @@ struct controller_impl { authorization.read_from_snapshot(snapshot); resource_limits.read_from_snapshot(snapshot); - db.set_revision( head_block_num() ); + db.set_revision( chain_head.block_num() ); db.create([](const auto& header){ // nothing to do }); @@ -1951,7 +1952,7 @@ struct controller_impl { const auto& tapos_block_summary = db.get(1); db.modify( tapos_block_summary, [&]( auto& bs ) { - bs.block_id = head_block_id(); + bs.block_id = chain_head.id(); }); genesis.initial_configuration.validate(); @@ -2030,7 +2031,7 @@ struct controller_impl { etrx.ref_block_prefix = 0; } else { etrx.expiration = time_point_sec{pending_block_time() + fc::microseconds(999'999)}; // Round up to nearest second to avoid appearing expired - etrx.set_reference_block( head_block_id() ); + etrx.set_reference_block( chain_head.id() ); } transaction_checktime_timer trx_timer(timer); @@ -2181,7 +2182,7 @@ struct controller_impl { if( is_builtin_activated( builtin_protocol_feature_t::disable_deferred_trxs_stage_1 ) || gtrx.expiration < pending_block_time() ) { trace = std::make_shared(); trace->id = gtrx.trx_id; - trace->block_num = head_block_num() + 1; + trace->block_num = chain_head.block_num() + 1; trace->block_time = pending_block_time(); trace->producer_block_id = pending_producer_block_id(); trace->scheduled = true; @@ -2552,34 +2553,35 @@ struct controller_impl { { EOS_ASSERT( !pending, block_validate_exception, "pending block already exists" ); - emit( block_start, head_block_num() + 1 ); + emit( block_start, chain_head.block_num() + 1 ); // at block level, no transaction specific logging is possible if (auto dm_logger = get_deep_mind_logger(false)) { // The head block represents the block just before this one that is about to start, so add 1 to get this block num - dm_logger->on_start_block(head_block_num() + 1); + dm_logger->on_start_block(chain_head.block_num() + 1); } - auto guard_pending = fc::make_scoped_exit([this, head_block_num=head_block_num()]() { + auto guard_pending = fc::make_scoped_exit([this, head_block_num=chain_head.block_num()]() { protocol_features.popped_blocks_to( head_block_num ); pending.reset(); }); - EOS_ASSERT( skip_db_sessions(s) || db.revision() == head_block_num(), database_exception, + EOS_ASSERT( skip_db_sessions(s) || db.revision() == chain_head.block_num(), database_exception, "db revision is not on par with head block", - ("db.revision()", db.revision())("controller_head_block", head_block_num())("fork_db_head_block", fork_db_head_block_num()) ); + ("db.revision()", db.revision())("controller_head_block", chain_head.block_num())("fork_db_head_block", fork_db_head_block_num()) ); - fork_db.apply( - [&](auto& forkdb) { // legacy - maybe_session session = skip_db_sessions(s) ? maybe_session() : maybe_session(db); - pending.emplace(std::move(session), *forkdb.chain_head, when, confirm_block_count, new_protocol_feature_activations); - }, - [&](auto& forkdb) { // instant-finality - maybe_session session = skip_db_sessions(s) ? maybe_session() : maybe_session(db); - building_block_input bbi{forkdb.chain_head->id(), forkdb.chain_head->timestamp(), when, forkdb.chain_head->get_scheduled_producer(when).producer_name, - new_protocol_feature_activations}; - pending.emplace(std::move(session), *forkdb.chain_head, bbi); - }); + std::visit(overloaded{ + [&](const block_state_legacy_ptr& head) { + maybe_session session = skip_db_sessions(s) ? maybe_session() : maybe_session(db); + pending.emplace(std::move(session), *head, when, confirm_block_count, new_protocol_feature_activations); + }, + [&](const block_state_ptr& head) { + maybe_session session = skip_db_sessions(s) ? maybe_session() : maybe_session(db); + building_block_input bbi{head->id(), head->timestamp(), when, head->get_scheduled_producer(when).producer_name, + new_protocol_feature_activations}; + pending.emplace(std::move(session), *head, bbi); + } + }, chain_head.internal()); pending->_block_status = s; pending->_producer_block_id = producer_block_id; @@ -2695,7 +2697,7 @@ struct controller_impl { auto trace = push_transaction( onbtrx, fc::time_point::maximum(), fc::microseconds::maximum(), gpo.configuration.min_transaction_cpu_usage, true, 0 ); if( trace->except ) { - wlog("onblock ${block_num} is REJECTING: ${entire_trace}",("block_num", head_block_num() + 1)("entire_trace", trace)); + wlog("onblock ${block_num} is REJECTING: ${entire_trace}",("block_num", chain_head.block_num() + 1)("entire_trace", trace)); } } catch( const std::bad_alloc& e ) { elog( "on block transaction failed due to a std::bad_alloc" ); @@ -2759,7 +2761,7 @@ struct controller_impl { }); } }; - fork_db.apply_if(process_new_proposer_policy); + fork_db.apply_savanna(process_new_proposer_policy); auto assembled_block = bb.assemble_block(thread_pool.get_executor(), protocol_features.get_protocol_feature_set(), fork_db, std::move(new_proposer_policy), @@ -2788,7 +2790,7 @@ struct controller_impl { const auto& cb = std::get(pending->_block_stage); auto add_completed_block = [&](auto& forkdb) { - const auto& bsp = std::get>(cb.bsp); + const auto& bsp = std::get>(cb.bsp); if( s == controller::block_status::incomplete ) { forkdb.add( bsp, mark_valid_t::yes, ignore_duplicate_t::no ); @@ -2796,23 +2798,26 @@ struct controller_impl { } else if (s != controller::block_status::irreversible) { forkdb.mark_valid( bsp ); } - forkdb.chain_head = bsp; + chain_head = block_handle{bsp}; emit( accepted_block, std::tie(bsp->block, bsp->id()) ); }; fork_db.apply(add_completed_block); - fork_db.apply_legacy([this](auto& forkdb) { + std::visit([&](const auto& head) { #warning todo: support deep_mind_logger even when in IF mode (use apply instead of apply_legacy) + if constexpr (std::is_same_v>) { // at block level, no transaction specific logging is possible if (auto* dm_logger = get_deep_mind_logger(false)) { - dm_logger->on_accepted_block(forkdb.chain_head); - }}); + dm_logger->on_accepted_block(head); + } + } + }, chain_head.internal()); if( s == controller::block_status::incomplete ) { - fork_db.apply_if([&](auto& forkdb) { - const auto& bsp = std::get>(cb.bsp); + fork_db.apply_savanna([&](auto& forkdb) { + const auto& bsp = std::get>(cb.bsp); uint16_t if_ext_id = instant_finality_extension::extension_id(); assert(bsp->header_exts.count(if_ext_id) > 0); // in all instant_finality block headers @@ -2830,16 +2835,18 @@ struct controller_impl { log_irreversible(); } - fork_db.apply_if([&](auto& forkdb) { create_and_send_vote_msg(forkdb.chain_head); }); + if ( s == controller::block_status::incomplete || s == controller::block_status::complete || s == controller::block_status::validated ) { + apply_savanna(chain_head, [&](const auto& head) { create_and_send_vote_msg(head); }); + } // TODO: temp transition to instant-finality, happens immediately after block with new_finalizer_policy - auto transition = [&](auto& forkdb) -> bool { - std::optional ext = forkdb.chain_head->block->extract_header_extension(instant_finality_extension::extension_id()); + auto transition = [&](const auto& head) -> bool { + std::optional ext = head->block->extract_header_extension(instant_finality_extension::extension_id()); if (ext) { const auto& if_extension = std::get(*ext); if (if_extension.new_finalizer_policy) { - ilog("Transition to instant finality happening after block ${b}", ("b", forkdb.chain_head->block_num())); - set_if_irreversible_block_id(forkdb.chain_head->id()); + ilog("Transition to instant finality happening after block ${b}", ("b", head->block_num())); + set_if_irreversible_block_id(head->id()); // cancel any proposed schedule changes, prepare for new ones under instant_finality const auto& gpo = db.get(); @@ -2857,8 +2864,8 @@ struct controller_impl { // See https://github.com/AntelopeIO/leap/issues/2070#issuecomment-1941901836 // [if todo] set values accurately // ----------------------------------------------------------------------------------------------- - auto start_block = forkdb.chain_head; - auto lib_block = forkdb.chain_head; + auto start_block = head; + auto lib_block = head; my_finalizers.set_default_safety_information( finalizer_safety_information{ .last_vote_range_start = block_timestamp_type(0), .last_vote = proposal_ref(start_block->id(), start_block->timestamp()), @@ -2871,8 +2878,8 @@ struct controller_impl { } return false; }; - if (fork_db.apply_legacy(transition)) { - fork_db.switch_from_legacy(); + if (apply_legacy(chain_head, transition)) { + chain_head = fork_db.switch_from_legacy(chain_head); } } catch (...) { @@ -3444,7 +3451,7 @@ struct controller_impl { } auto do_accept_block = [&](auto& forkdb) { - if constexpr (std::is_same_v>) + if constexpr (std::is_same_v>) forkdb.add( bsp, mark_valid_t::no, ignore_duplicate_t::no ); emit( accepted_block_header, std::tie(bsp->block, bsp->id()) ); @@ -3476,14 +3483,14 @@ struct controller_impl { try { const auto& b = bsp->block; - if( conf.terminate_at_block > 0 && conf.terminate_at_block <= head_block_num()) { + if( conf.terminate_at_block > 0 && conf.terminate_at_block <= chain_head.block_num()) { ilog("Reached configured maximum block ${num}; terminating", ("num", conf.terminate_at_block) ); shutdown(); return; } auto do_push = [&](auto& forkdb) { - if constexpr (std::is_same_v>) { + if constexpr (std::is_same_v>) { forkdb.add( bsp, mark_valid_t::no, ignore_duplicate_t::no ); } @@ -3494,7 +3501,7 @@ struct controller_impl { emit( accepted_block_header, std::tie(bsp->block, bsp->id()) ); if( read_mode != db_read_mode::IRREVERSIBLE ) { - if constexpr (std::is_same_v>) + if constexpr (std::is_same_v>) maybe_switch_forks( br, forkdb.pending_head(), s, forked_branch_cb, trx_lookup ); } else { log_irreversible(); @@ -3517,7 +3524,7 @@ struct controller_impl { EOS_ASSERT( (s == controller::block_status::irreversible || s == controller::block_status::validated), block_validate_exception, "invalid block status for replay" ); - if( conf.terminate_at_block > 0 && conf.terminate_at_block <= head_block_num() ) { + if( conf.terminate_at_block > 0 && conf.terminate_at_block <= chain_head.block_num() ) { ilog("Reached configured maximum block ${num}; terminating", ("num", conf.terminate_at_block) ); shutdown(); return; @@ -3529,11 +3536,14 @@ struct controller_impl { check_protocol_features(timestamp, cur_features, new_features); }; - auto do_push = [&](auto& forkdb) { - if constexpr (std::is_same_v>) { - auto bsp = std::make_shared( - *forkdb.chain_head, b, protocol_features.get_protocol_feature_set(), validator, skip_validate_signee); + BSP bsp; + std::visit([&](const auto& head) { + if constexpr (std::is_same_v>) + bsp = std::make_shared(*head, b, protocol_features.get_protocol_feature_set(),validator, skip_validate_signee); + }, chain_head.internal()); + auto do_push = [&](auto& forkdb) { + if constexpr (std::is_same_v>) { if (s != controller::block_status::irreversible) { forkdb.add(bsp, mark_valid_t::no, ignore_duplicate_t::yes); } @@ -3568,7 +3578,7 @@ struct controller_impl { auto maybe_switch = [&](auto& forkdb) { if (read_mode != db_read_mode::IRREVERSIBLE) { auto fork_head = forkdb.head(); - if (forkdb.chain_head->id() != fork_head->id()) { + if (chain_head.id() != fork_head->id()) { controller::block_report br; maybe_switch_forks(br, fork_head, fork_head->is_valid() ? controller::block_status::validated : controller::block_status::complete, cb, trx_lookup); @@ -3585,31 +3595,30 @@ struct controller_impl { { auto do_maybe_switch_forks = [&](auto& forkdb) { bool head_changed = true; - auto& head = forkdb.chain_head; - if( new_head->header.previous == head->id() ) { + if( new_head->header.previous == chain_head.id() ) { try { apply_block( br, new_head, s, trx_lookup ); } catch ( const std::exception& e ) { forkdb.remove( new_head->id() ); throw; } - } else if( new_head->id() != head->id() ) { + } else if( new_head->id() != chain_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", log_fork_comparison(*head))("n", log_fork_comparison(*new_head))); + ("current_head_id", chain_head.id())("current_head_num", chain_head.block_num())("new_head_id", new_head->id())("new_head_num", new_head->block_num()) + ("c", log_fork_comparison(chain_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)) { - dm_logger->on_switch_forks(head->id(), new_head->id()); + dm_logger->on_switch_forks(chain_head.id(), new_head->id()); } - auto branches = forkdb.fetch_branch_from( new_head->id(), head->id() ); + auto branches = forkdb.fetch_branch_from( new_head->id(), chain_head.id() ); if( branches.second.size() > 0 ) { for( auto itr = branches.second.begin(); itr != branches.second.end(); ++itr ) { pop_block(); } - EOS_ASSERT( head_block_id() == branches.second.back()->header.previous, fork_database_exception, + EOS_ASSERT( chain_head.id() == branches.second.back()->header.previous, fork_database_exception, "loss of sync between fork_db and chainbase during fork switch" ); // _should_ never fail if( forked_cb ) { @@ -3652,7 +3661,7 @@ struct controller_impl { for( auto itr = applied_itr; itr != branches.first.end(); ++itr ) { pop_block(); } - EOS_ASSERT( head_block_id() == branches.second.back()->header.previous, fork_database_exception, + EOS_ASSERT( chain_head.id() == branches.second.back()->header.previous, fork_database_exception, "loss of sync between fork_db and chainbase during fork switch reversal" ); // _should_ never fail // re-apply good blocks @@ -3693,7 +3702,7 @@ struct controller_impl { if( pending ) { applied_trxs = pending->extract_trx_metas(); pending.reset(); - protocol_features.popped_blocks_to( head_block_num() ); + protocol_features.popped_blocks_to( chain_head.block_num() ); } return applied_trxs; } @@ -3769,7 +3778,7 @@ struct controller_impl { //Look for expired transactions in the deduplication list, and remove them. auto& transaction_idx = db.get_mutable_index(); const auto& dedupe_index = transaction_idx.indices().get(); - auto now = is_building_block() ? pending_block_time() : head_block_time().to_time_point(); + auto now = is_building_block() ? pending_block_time() : chain_head.block_time().to_time_point(); const auto total = dedupe_index.size(); uint32_t num_removed = 0; while( (!dedupe_index.empty()) && ( now > dedupe_index.begin()->expiration.to_time_point() ) ) { @@ -3922,7 +3931,7 @@ struct controller_impl { on_block_act.account = config::system_account_name; on_block_act.name = "onblock"_n; on_block_act.authorization = vector{{config::system_account_name, config::active_name}}; - on_block_act.data = fc::raw::pack(head_block_header()); + on_block_act.data = fc::raw::pack(chain_head.header()); signed_transaction trx; trx.actions.emplace_back(std::move(on_block_act)); @@ -3932,7 +3941,7 @@ struct controller_impl { trx.ref_block_prefix = 0; } else { trx.expiration = time_point_sec{pending_block_time() + fc::microseconds(999'999)}; // Round up to nearest second to avoid appearing expired - trx.set_reference_block( head_block_id() ); + trx.set_reference_block( chain_head.id() ); } return trx; @@ -4041,7 +4050,7 @@ struct controller_impl { } bool is_builtin_activated( builtin_protocol_feature_t f )const { - uint32_t current_block_num = head_block_num(); + uint32_t current_block_num = chain_head.block_num(); if( pending ) { ++current_block_num; @@ -4297,7 +4306,7 @@ vector controller::get_preactivated_protocol_features()const { } void controller::validate_protocol_features( const vector& features_to_activate )const { - my->check_protocol_features( my->head_block_time(), + my->check_protocol_features( my->chain_head.block_time(), my->head_activated_protocol_features()->protocol_features, features_to_activate ); } @@ -4364,16 +4373,16 @@ std::optional controller::create_block_handle( const block_id_type } void controller::push_block( block_report& br, - const block_handle& b, + const block_handle& bh, const forked_callback_t& forked_cb, const trx_meta_cache_lookup& trx_lookup ) { validate_db_available_size(); - std::visit([&](const auto& bsp) { my->push_block( br, bsp, forked_cb, trx_lookup); }, b.bsp); + std::visit([&](const auto& bsp) { my->push_block( br, bsp, forked_cb, trx_lookup); }, bh.internal()); } -void controller::accept_block(const block_handle& b) { - std::visit([&](const auto& bsp) { my->accept_block(bsp); }, b.bsp); +void controller::accept_block(const block_handle& bh) { + std::visit([&](const auto& bsp) { my->accept_block(bsp); }, bh.internal()); } transaction_trace_ptr controller::push_transaction( const transaction_metadata_ptr& trx, @@ -4442,34 +4451,35 @@ void controller::set_disable_replay_opts( bool v ) { } uint32_t controller::head_block_num()const { - return my->head_block_num(); + return my->chain_head.block_num(); } block_timestamp_type controller::head_block_timestamp()const { - return my->head_block_time(); + return my->chain_head.block_time(); } time_point controller::head_block_time()const { - return my->head_block_time(); + return my->chain_head.block_time(); } block_id_type controller::head_block_id()const { - return my->head_block_id(); + return my->chain_head.id(); } account_name controller::head_block_producer()const { - return my->head_block_producer(); + return my->chain_head.producer(); } const block_header& controller::head_block_header()const { - return my->head_block_header(); + return my->chain_head.header(); } block_state_legacy_ptr controller::head_block_state_legacy()const { // returns null after instant finality activated - return my->fork_db.apply_legacy( - [](auto& forkdb) -> block_state_legacy_ptr { return forkdb.chain_head; }); + return apply_legacy(my->chain_head, [](const auto& head) { + return head; + }); } const signed_block_ptr& controller::head_block()const { - return my->head_block(); + return my->chain_head.block(); } uint32_t controller::fork_db_head_block_num()const { @@ -4633,7 +4643,7 @@ int64_t controller_impl::set_proposed_producers( vector prod assert(pending); const auto& gpo = db.get(); - auto cur_block_num = head_block_num() + 1; + auto cur_block_num = chain_head.block_num() + 1; producer_authority_schedule sch; @@ -4653,7 +4663,7 @@ int64_t controller_impl::set_proposed_producers( vector prod int64_t controller_impl::set_proposed_producers_legacy( vector producers ) { const auto& gpo = db.get(); - auto cur_block_num = head_block_num() + 1; + auto cur_block_num = chain_head.block_num() + 1; if( producers.size() == 0 && is_builtin_activated( builtin_protocol_feature_t::disallow_empty_producer_schedule ) ) { return -1; diff --git a/libraries/chain/fork_database.cpp b/libraries/chain/fork_database.cpp index 5c5e4e29b9..9551f421e0 100644 --- a/libraries/chain/fork_database.cpp +++ b/libraries/chain/fork_database.cpp @@ -48,6 +48,10 @@ namespace eosio::chain { return r; } + std::string log_fork_comparison(const block_handle& bh) { + return std::visit([](const auto& bsp) { return log_fork_comparison(*bsp); }, bh.internal()); + } + struct by_block_id; struct by_best_branch; struct by_prev; @@ -751,9 +755,9 @@ namespace eosio::chain { }); } else { // file is instant-finality data, so switch to fork_database_if_t - fork_db_if = std::make_unique(fork_database_if_t::magic_number); + fork_db_savanna = std::make_unique(fork_database_if_t::magic_number); legacy = false; - apply_if([&](auto& forkdb) { + apply_savanna([&](auto& forkdb) { forkdb.open(fork_db_file, validator); }); } @@ -761,18 +765,19 @@ namespace eosio::chain { } } - void fork_database::switch_from_legacy() { + block_handle fork_database::switch_from_legacy(const block_handle& bh) { // no need to close fork_db because we don't want to write anything out, file is removed on open // threads may be accessing (or locked on mutex about to access legacy forkdb) so don't delete it until program exit assert(legacy); - block_state_legacy_ptr head = fork_db_legacy->chain_head; // will throw if called after transistion + assert(std::holds_alternative(bh.internal())); + block_state_legacy_ptr head = std::get(bh.internal()); // will throw if called after transistion auto new_head = std::make_shared(*head); - fork_db_if = std::make_unique(fork_database_if_t::magic_number); + fork_db_savanna = std::make_unique(fork_database_if_t::magic_number); legacy = false; - apply_if([&](auto& forkdb) { - forkdb.chain_head = new_head; + apply_savanna([&](auto& forkdb) { forkdb.reset_root(*new_head); }); + return block_handle{new_head}; } block_branch_t fork_database::fetch_branch_from_head() const { diff --git a/libraries/chain/include/eosio/chain/block_handle.hpp b/libraries/chain/include/eosio/chain/block_handle.hpp new file mode 100644 index 0000000000..2e4ae5cbe8 --- /dev/null +++ b/libraries/chain/include/eosio/chain/block_handle.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include +#include + +namespace eosio::chain { + +// Created via controller::create_block_handle(const block_id_type& id, const signed_block_ptr& b) +// Valid to request id and signed_block_ptr it was created from. +struct block_handle { +private: + std::variant _bsp; + +public: + block_handle() = default; + explicit block_handle(block_state_legacy_ptr bsp) : _bsp(std::move(bsp)) {} + explicit block_handle(block_state_ptr bsp) : _bsp(std::move(bsp)) {} + + void set_internal(block_state_legacy_ptr bsp) { _bsp = std::move(bsp); } + void set_internal(block_state_ptr bsp) { _bsp = std::move(bsp); } + // Avoid using internal block_state/block_state_legacy as those types are internal to controller. + const auto& internal() const { return _bsp; } + + uint32_t block_num() const { return std::visit([](const auto& bsp) { return bsp->block_num(); }, _bsp); } + block_timestamp_type block_time() const { return std::visit([](const auto& bsp) { return bsp->timestamp(); }, _bsp); }; + const block_id_type& id() const { return std::visit([](const auto& bsp) -> const block_id_type& { return bsp->id(); }, _bsp); } + const block_id_type& previous() const { return std::visit([](const auto& bsp) -> const block_id_type& { return bsp->previous(); }, _bsp); } + const signed_block_ptr& block() const { return std::visit([](const auto& bsp) -> const signed_block_ptr& { return bsp->block; }, _bsp); } + const block_header& header() const { return std::visit([](const auto& bsp) -> const block_header& { return bsp->header; }, _bsp); }; + account_name producer() const { return std::visit([](const auto& bsp) { return bsp->producer(); }, _bsp); } +}; + +} // namespace eosio::chain diff --git a/libraries/chain/include/eosio/chain/controller.hpp b/libraries/chain/include/eosio/chain/controller.hpp index dd87686889..e45cb75deb 100644 --- a/libraries/chain/include/eosio/chain/controller.hpp +++ b/libraries/chain/include/eosio/chain/controller.hpp @@ -1,6 +1,7 @@ #pragma once #include #include +#include #include #include #include @@ -58,17 +59,6 @@ namespace eosio::chain { using block_signal_params = std::tuple; - // Created via create_block_handle(const block_id_type& id, const signed_block_ptr& b) - // Valid to request id and signed_block_ptr it was created from. - // Avoid using internal block_state/block_state_legacy as those types are internal to controller. - struct block_handle { - std::variant bsp; - - uint32_t block_num() const { return std::visit([](const auto& bsp) { return bsp->block_num(); }, bsp); } - block_id_type id() const { return std::visit([](const auto& bsp) { return bsp->id(); }, bsp); } - signed_block_ptr block() const { return std::visit([](const auto& bsp) { return bsp->block; }, bsp); } - }; - enum class db_read_mode { HEAD, IRREVERSIBLE, diff --git a/libraries/chain/include/eosio/chain/fork_database.hpp b/libraries/chain/include/eosio/chain/fork_database.hpp index a40cbeadc6..ab2e9e441c 100644 --- a/libraries/chain/include/eosio/chain/fork_database.hpp +++ b/libraries/chain/include/eosio/chain/fork_database.hpp @@ -1,6 +1,7 @@ #pragma once #include #include +#include namespace eosio::chain { @@ -14,6 +15,7 @@ namespace eosio::chain { // Used for logging of comparison values used for best fork determination std::string log_fork_comparison(const block_state& bs); std::string log_fork_comparison(const block_state_legacy& bs); + std::string log_fork_comparison(const block_handle& bh); /** * @class fork_database_t @@ -83,9 +85,6 @@ namespace eosio::chain { bsp_t head() const; bsp_t pending_head() const; - // only accessed by main thread, no mutex protection - bsp_t chain_head; - /** * 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 @@ -140,7 +139,7 @@ namespace eosio::chain { const std::filesystem::path data_dir; std::atomic legacy = true; std::unique_ptr fork_db_legacy; - std::unique_ptr fork_db_if; + std::unique_ptr fork_db_savanna; public: explicit fork_database(const std::filesystem::path& data_dir); ~fork_database(); // close on destruction @@ -150,9 +149,9 @@ namespace eosio::chain { void close(); // expected to be called from main thread, accesses chain_head - void switch_from_legacy(); + block_handle switch_from_legacy(const block_handle& bh); - bool fork_db_if_present() const { return !!fork_db_if; } + bool fork_db_if_present() const { return !!fork_db_savanna; } bool fork_db_legacy_present() const { return !!fork_db_legacy; } // see fork_database_t::fetch_branch(forkdb->head()->id()) @@ -164,13 +163,13 @@ namespace eosio::chain { if (legacy) { f(*fork_db_legacy); } else { - f(*fork_db_if); + f(*fork_db_savanna); } } else { if (legacy) { return f(*fork_db_legacy); } else { - return f(*fork_db_if); + return f(*fork_db_savanna); } } } @@ -181,27 +180,27 @@ namespace eosio::chain { if (legacy) { f(*fork_db_legacy); } else { - f(*fork_db_if); + f(*fork_db_savanna); } } else { if (legacy) { return f(*fork_db_legacy); } else { - return f(*fork_db_if); + return f(*fork_db_savanna); } } } /// Apply for when only need lambda executed when in instant-finality mode template - R apply_if(const F& f) { + R apply_savanna(const F& f) { if constexpr (std::is_same_v) { if (!legacy) { - f(*fork_db_if); + f(*fork_db_savanna); } } else { if (!legacy) { - return f(*fork_db_if); + return f(*fork_db_savanna); } return {}; } @@ -223,20 +222,20 @@ namespace eosio::chain { } /// @param legacy_f the lambda to execute if in legacy mode - /// @param if_f the lambda to execute if in instant-finality mode - template - R apply(const LegacyF& legacy_f, const IfF& if_f) { + /// @param savanna_f the lambda to execute if in savanna instant-finality mode + template + R apply(const LegacyF& legacy_f, const SavannaF& savanna_f) { if constexpr (std::is_same_v) { if (legacy) { legacy_f(*fork_db_legacy); } else { - if_f(*fork_db_if); + savanna_f(*fork_db_savanna); } } else { if (legacy) { return legacy_f(*fork_db_legacy); } else { - return if_f(*fork_db_if); + return savanna_f(*fork_db_savanna); } } } From 1c7aa0163e198acc2cbaa3c0c7c445f03ab39585 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Mon, 4 Mar 2024 16:23:02 -0600 Subject: [PATCH 2/2] GH-2141 Rename apply_legacy and apply_savanna to apply_l and apply_s --- libraries/chain/controller.cpp | 33 +++++++------ libraries/chain/fork_database.cpp | 12 ++--- .../include/eosio/chain/fork_database.hpp | 46 +++++++++---------- 3 files changed, 47 insertions(+), 44 deletions(-) diff --git a/libraries/chain/controller.cpp b/libraries/chain/controller.cpp index 0c3664f460..34b74ab41c 100644 --- a/libraries/chain/controller.cpp +++ b/libraries/chain/controller.cpp @@ -125,8 +125,9 @@ struct qc_data_t { // and specify `weak`. }; +// apply savanna block_state template -R apply_savanna(const block_handle& bh, F&& f) { +R apply_s(const block_handle& bh, F&& f) { if constexpr (std::is_same_v) std::visit(overloaded{[&](const block_state_legacy_ptr&) {}, [&](const block_state_ptr& head) { std::forward(f)(head); }}, bh.internal()); @@ -135,8 +136,9 @@ R apply_savanna(const block_handle& bh, F&& f) { [&](const block_state_ptr& head) -> R { return std::forward(f)(head); }}, bh.internal()); } +// apply legancy block_state_legacy template -R apply_legacy(const block_handle& bh, F&& f) { +R apply_l(const block_handle& bh, F&& f) { if constexpr (std::is_same_v) std::visit(overloaded{[&](const block_state_legacy_ptr& head) { std::forward(f)(head); }, [&](const block_state_ptr&) {}}, bh.internal()); @@ -486,8 +488,9 @@ struct building_block { bool is_legacy() const { return std::holds_alternative(v); } + // apply legacy, building_block_legacy template - R apply_legacy(F&& f) { + R apply_l(F&& f) { if constexpr (std::is_same_v) std::visit(overloaded{[&](building_block_legacy& bb) { std::forward(f)(bb); }, [&](building_block_if& bb) {}}, v); @@ -676,7 +679,7 @@ struct building_block { // we are simulating a block received from the network. Use the embedded qc from the block qc_data = std::move(validating_qc_data); } else { - fork_db.apply_savanna([&](const auto& forkdb) { + fork_db.apply_s([&](const auto& forkdb) { auto branch = forkdb.fetch_branch(parent_id()); std::optional qc; for( auto it = branch.begin(); it != branch.end(); ++it ) { @@ -1303,7 +1306,7 @@ struct controller_impl { chain_head = block_handle{head}; }; - fork_db.apply_legacy(init_blockchain); // assuming here that genesis_state is always dpos + fork_db.apply_l(init_blockchain); // assuming here that genesis_state is always dpos db.set_revision( chain_head.block_num() ); initialize_database(genesis); @@ -1609,7 +1612,7 @@ struct controller_impl { .last_vote = {}, .lock = proposal_ref(lib->id(), lib->timestamp()) }); }; - fork_db.apply_savanna(set_finalizer_defaults); + fork_db.apply_s(set_finalizer_defaults); } else { // we are past the IF transition. auto set_finalizer_defaults = [&](auto& forkdb) -> void { @@ -1619,7 +1622,7 @@ struct controller_impl { .last_vote = {}, .lock = proposal_ref(lib->id(), lib->timestamp()) }); }; - fork_db.apply_savanna(set_finalizer_defaults); + fork_db.apply_s(set_finalizer_defaults); } } } @@ -1791,7 +1794,7 @@ struct controller_impl { chain_head = block_handle{head}; static_cast(*head) = head_header_state; }; - fork_db.apply_legacy(read_block_state_section); + fork_db.apply_l(read_block_state_section); controller_index_set::walk_indices([this, &snapshot, &header]( auto utils ){ using value_t = typename decltype(utils)::index_t::value_type; @@ -2657,7 +2660,7 @@ struct controller_impl { const auto& gpo = db.get(); // instant finality uses alternative method for chaning producer schedule - bb.apply_legacy([&](building_block::building_block_legacy& bb_legacy) { + bb.apply_l([&](building_block::building_block_legacy& bb_legacy) { pending_block_header_state_legacy& pbhs = bb_legacy.pending_block_header_state; if( gpo.proposed_schedule_block_num && // if there is a proposed schedule that was proposed in a block ... @@ -2761,7 +2764,7 @@ struct controller_impl { }); } }; - fork_db.apply_savanna(process_new_proposer_policy); + fork_db.apply_s(process_new_proposer_policy); auto assembled_block = bb.assemble_block(thread_pool.get_executor(), protocol_features.get_protocol_feature_set(), fork_db, std::move(new_proposer_policy), @@ -2816,7 +2819,7 @@ struct controller_impl { }, chain_head.internal()); if( s == controller::block_status::incomplete ) { - fork_db.apply_savanna([&](auto& forkdb) { + fork_db.apply_s([&](auto& forkdb) { const auto& bsp = std::get>(cb.bsp); uint16_t if_ext_id = instant_finality_extension::extension_id(); @@ -2836,7 +2839,7 @@ struct controller_impl { } if ( s == controller::block_status::incomplete || s == controller::block_status::complete || s == controller::block_status::validated ) { - apply_savanna(chain_head, [&](const auto& head) { create_and_send_vote_msg(head); }); + apply_s(chain_head, [&](const auto& head) { create_and_send_vote_msg(head); }); } // TODO: temp transition to instant-finality, happens immediately after block with new_finalizer_policy @@ -2878,7 +2881,7 @@ struct controller_impl { } return false; }; - if (apply_legacy(chain_head, transition)) { + if (apply_l(chain_head, transition)) { chain_head = fork_db.switch_from_legacy(chain_head); } @@ -3727,7 +3730,7 @@ struct controller_impl { void update_producers_authority() { // this is not called when hotstuff is activated auto& bb = std::get(pending->_block_stage); - bb.apply_legacy([this](building_block::building_block_legacy& legacy_header) { + bb.apply_l([this](building_block::building_block_legacy& legacy_header) { pending_block_header_state_legacy& pbhs = legacy_header.pending_block_header_state; const auto& producers = pbhs.active_schedule.producers; @@ -4473,7 +4476,7 @@ const block_header& controller::head_block_header()const { block_state_legacy_ptr controller::head_block_state_legacy()const { // returns null after instant finality activated - return apply_legacy(my->chain_head, [](const auto& head) { + return apply_l(my->chain_head, [](const auto& head) { return head; }); } diff --git a/libraries/chain/fork_database.cpp b/libraries/chain/fork_database.cpp index 9551f421e0..6d4de818b3 100644 --- a/libraries/chain/fork_database.cpp +++ b/libraries/chain/fork_database.cpp @@ -713,7 +713,7 @@ namespace eosio::chain { fork_database::fork_database(const std::filesystem::path& data_dir) : data_dir(data_dir) // currently needed because chain_head is accessed before fork database open - , fork_db_legacy{std::make_unique(fork_database_legacy_t::legacy_magic_number)} + , fork_db_l{std::make_unique(fork_database_legacy_t::legacy_magic_number)} { } @@ -750,14 +750,14 @@ namespace eosio::chain { if (totem == fork_database_legacy_t::legacy_magic_number) { // fork_db_legacy created in constructor - apply_legacy([&](auto& forkdb) { + apply_l([&](auto& forkdb) { forkdb.open(fork_db_file, validator); }); } else { // file is instant-finality data, so switch to fork_database_if_t - fork_db_savanna = std::make_unique(fork_database_if_t::magic_number); + fork_db_s = std::make_unique(fork_database_if_t::magic_number); legacy = false; - apply_savanna([&](auto& forkdb) { + apply_s([&](auto& forkdb) { forkdb.open(fork_db_file, validator); }); } @@ -772,9 +772,9 @@ namespace eosio::chain { assert(std::holds_alternative(bh.internal())); block_state_legacy_ptr head = std::get(bh.internal()); // will throw if called after transistion auto new_head = std::make_shared(*head); - fork_db_savanna = std::make_unique(fork_database_if_t::magic_number); + fork_db_s = std::make_unique(fork_database_if_t::magic_number); legacy = false; - apply_savanna([&](auto& forkdb) { + apply_s([&](auto& forkdb) { forkdb.reset_root(*new_head); }); return block_handle{new_head}; diff --git a/libraries/chain/include/eosio/chain/fork_database.hpp b/libraries/chain/include/eosio/chain/fork_database.hpp index ab2e9e441c..b7f18964aa 100644 --- a/libraries/chain/include/eosio/chain/fork_database.hpp +++ b/libraries/chain/include/eosio/chain/fork_database.hpp @@ -138,8 +138,8 @@ namespace eosio::chain { class fork_database { const std::filesystem::path data_dir; std::atomic legacy = true; - std::unique_ptr fork_db_legacy; - std::unique_ptr fork_db_savanna; + std::unique_ptr fork_db_l; // legacy + std::unique_ptr fork_db_s; // savanna public: explicit fork_database(const std::filesystem::path& data_dir); ~fork_database(); // close on destruction @@ -151,8 +151,8 @@ namespace eosio::chain { // expected to be called from main thread, accesses chain_head block_handle switch_from_legacy(const block_handle& bh); - bool fork_db_if_present() const { return !!fork_db_savanna; } - bool fork_db_legacy_present() const { return !!fork_db_legacy; } + bool fork_db_if_present() const { return !!fork_db_s; } + bool fork_db_legacy_present() const { return !!fork_db_l; } // see fork_database_t::fetch_branch(forkdb->head()->id()) block_branch_t fetch_branch_from_head() const; @@ -161,15 +161,15 @@ namespace eosio::chain { R apply(const F& f) { if constexpr (std::is_same_v) { if (legacy) { - f(*fork_db_legacy); + f(*fork_db_l); } else { - f(*fork_db_savanna); + f(*fork_db_s); } } else { if (legacy) { - return f(*fork_db_legacy); + return f(*fork_db_l); } else { - return f(*fork_db_savanna); + return f(*fork_db_s); } } } @@ -178,29 +178,29 @@ namespace eosio::chain { R apply(const F& f) const { if constexpr (std::is_same_v) { if (legacy) { - f(*fork_db_legacy); + f(*fork_db_l); } else { - f(*fork_db_savanna); + f(*fork_db_s); } } else { if (legacy) { - return f(*fork_db_legacy); + return f(*fork_db_l); } else { - return f(*fork_db_savanna); + return f(*fork_db_s); } } } - /// Apply for when only need lambda executed when in instant-finality mode + /// Apply for when only need lambda executed when in savanna (instant-finality) mode template - R apply_savanna(const F& f) { + R apply_s(const F& f) { if constexpr (std::is_same_v) { if (!legacy) { - f(*fork_db_savanna); + f(*fork_db_s); } } else { if (!legacy) { - return f(*fork_db_savanna); + return f(*fork_db_s); } return {}; } @@ -208,14 +208,14 @@ namespace eosio::chain { /// Apply for when only need lambda executed when in legacy mode template - R apply_legacy(const F& f) { + R apply_l(const F& f) { if constexpr (std::is_same_v) { if (legacy) { - f(*fork_db_legacy); + f(*fork_db_l); } } else { if (legacy) { - return f(*fork_db_legacy); + return f(*fork_db_l); } return {}; } @@ -227,15 +227,15 @@ namespace eosio::chain { R apply(const LegacyF& legacy_f, const SavannaF& savanna_f) { if constexpr (std::is_same_v) { if (legacy) { - legacy_f(*fork_db_legacy); + legacy_f(*fork_db_l); } else { - savanna_f(*fork_db_savanna); + savanna_f(*fork_db_s); } } else { if (legacy) { - return legacy_f(*fork_db_legacy); + return legacy_f(*fork_db_l); } else { - return savanna_f(*fork_db_savanna); + return savanna_f(*fork_db_s); } } }