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: Transition from dpos to instant-finality #2085

Merged
merged 19 commits into from
Jan 16, 2024
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
3b15160
GH-2045 Rename finalize_block to finish_block to avoid confusion with…
heifner Jan 12, 2024
8408763
Merge remote-tracking branch 'origin/gh_2034_part2' into GH-2045-if-t…
heifner Jan 13, 2024
1c3315a
Merge remote-tracking branch 'origin/gh_2034_part2' into GH-2045-if-t…
heifner Jan 13, 2024
fe1d3bb
Merge remote-tracking branch 'origin/gh_2034_part2' into GH-2045-if-t…
heifner Jan 13, 2024
a482982
GH-2045 Add get_data_dir()
heifner Jan 14, 2024
4e631ae
GH-2045 Add constructor for transition from block_state_legacy to blo…
heifner Jan 14, 2024
abdfa68
GH-2045 Fix when active_producer_policy updated, done at end of block…
heifner Jan 14, 2024
61a595f
GH-2045 Add transition from dpos fork database to instant finality fo…
heifner Jan 14, 2024
c3e8423
GH-2045 Fix assert and use block exception type
heifner Jan 15, 2024
07f1036
GH-2045 Add block_token as a wrapper of block_state and block_state_l…
heifner Jan 15, 2024
9b39982
GH-2045 cleanup implementation
heifner Jan 15, 2024
03f2322
GH-2045 Fix proposer_policy switching time. Enable instant-finality p…
heifner Jan 15, 2024
7962634
GH-2045 Serialize all block_header_state and block_state data
heifner Jan 15, 2024
7c59cf3
GH-2045 Fix spelling
heifner Jan 15, 2024
d0a1e07
GH-2045 Don't export qcs
heifner Jan 15, 2024
b5dfdd4
GH-2045 Fix for next_producers when no pending
heifner Jan 15, 2024
35705b3
GH-2045 Removed a warning and renamed hs_irreversible_block_num
heifner Jan 15, 2024
6b62496
GH-2045 Misc cleanup
heifner Jan 15, 2024
852f69e
GH-2045 No need to close or open fork_db
heifner Jan 15, 2024
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
2 changes: 1 addition & 1 deletion docs/block_production/lifecycle.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ flowchart TD
direction TB
start -- "stage = Ø" --> sb
sb("start_block()"):::fun -- "stage = building_block" --> et
et["execute transactions" ] -- "stage = building_block" --> fb("finalize_block()"):::fun
et["execute transactions" ] -- "stage = building_block" --> fb("finish_block()"):::fun
fb -- "stage = assembled block" --> cb["add transaction metadata and create completed block"]
cb -- "stage = completed block" --> commit("commit_block() (where we [maybe] add to fork_db and mark valid)"):::fun

Expand Down
7 changes: 4 additions & 3 deletions libraries/chain/block_header_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,8 @@ block_header_state block_header_state::next(block_header_state_input& input) con

if(!proposer_policies.empty()) {
auto it = proposer_policies.begin();
if (it->first <= input.timestamp) {
// -1 since this is called after the block is built, this will be the active schedule for the next block
if (it->first.slot <= input.timestamp.slot - 1) {
result.active_proposer_policy = it->second;
result.header.schedule_version = header.schedule_version + 1;
result.active_proposer_policy->proposer_schedule.version = result.header.schedule_version;
Expand All @@ -108,7 +109,7 @@ block_header_state block_header_state::next(block_header_state_input& input) con

if (input.new_proposer_policy) {
// called when assembling the block
result.proposer_policies[result.header.timestamp] = input.new_proposer_policy;
result.proposer_policies[input.new_proposer_policy->active_time] = input.new_proposer_policy;
}

// finalizer policy
Expand Down Expand Up @@ -181,7 +182,7 @@ block_header_state block_header_state::next(const signed_block_header& h, const

// retrieve instant_finality_extension data from block header extension
// --------------------------------------------------------------------
EOS_ASSERT(exts.count(instant_finality_extension::extension_id() > 0), misc_exception,
EOS_ASSERT(exts.count(instant_finality_extension::extension_id()) > 0, invalid_block_header_extension,
"Instant Finality Extension is expected to be present in all block headers after switch to IF");
auto if_entry = exts.lower_bound(instant_finality_extension::extension_id());
auto& if_ext = std::get<instant_finality_extension>(if_entry->second);
Expand Down
25 changes: 24 additions & 1 deletion libraries/chain/block_state.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include <eosio/chain/block_state.hpp>
#include <eosio/chain/block_header_state_utils.hpp>
#include <eosio/chain/block_state_legacy.hpp>
#include <eosio/chain/exceptions.hpp>

namespace eosio::chain {
Expand All @@ -16,7 +17,29 @@ block_state::block_state(const block_header_state& bhs, deque<transaction_metada
, block(std::make_shared<signed_block>(signed_block_header{bhs.header})) // [greg todo] do we need signatures?
, pub_keys_recovered(true) // probably not needed
, cached_trxs(std::move(trx_metas))
{}
{
block->transactions = std::move(trx_receipts);
}

// Used for transition from dbpos to instant-finality
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Used for transition from dbpos to instant-finality
// Used for transition from dpos to instant-finality

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

block_state::block_state(const block_state_legacy& bsp) {
block_header_state::id = bsp.id();
header = bsp.header;
activated_protocol_features = bsp.activated_protocol_features;
std::optional<block_header_extension> ext = bsp.block->extract_header_extension(instant_finality_extension::extension_id());
assert(ext); // required by current transistion mechanism
greg7mdp marked this conversation as resolved.
Show resolved Hide resolved
const auto& if_extension = std::get<instant_finality_extension>(*ext);
assert(if_extension.new_finalizer_policy); // required by current transistion mechanism
greg7mdp marked this conversation as resolved.
Show resolved Hide resolved
active_finalizer_policy = std::make_shared<finalizer_policy>(*if_extension.new_finalizer_policy);
active_proposer_policy = std::make_shared<proposer_policy>();
active_proposer_policy->active_time = bsp.timestamp();
active_proposer_policy->proposer_schedule = bsp.active_schedule;
header_exts = bsp.header_exts; // not needed, but copy over just in case
block = bsp.block;
validated = bsp.is_valid();
pub_keys_recovered = bsp._pub_keys_recovered;
cached_trxs = bsp._cached_trxs;
}

deque<transaction_metadata_ptr> block_state::extract_trxs_metas() {
pub_keys_recovered = false;
Expand Down
284 changes: 156 additions & 128 deletions libraries/chain/controller.cpp

Large diffs are not rendered by default.

7 changes: 6 additions & 1 deletion libraries/chain/fork_database.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ namespace eosio::chain {
fork_multi_index_type index;
bsp root; // Only uses the block_header_state_legacy portion
bsp head;
std::filesystem::path datadir;
const std::filesystem::path datadir;

explicit fork_database_impl( const std::filesystem::path& data_dir ) : datadir(data_dir) {}

Expand Down Expand Up @@ -102,6 +102,11 @@ namespace eosio::chain {
my->open_impl( validator );
}

template<class bsp>
std::filesystem::path fork_database<bsp>::get_data_dir() const {
return my->datadir;
}

template<class bsp>
void fork_database_impl<bsp>::open_impl( validator_t& validator ) {
if (!std::filesystem::is_directory(datadir))
Expand Down
2 changes: 1 addition & 1 deletion libraries/chain/hotstuff/chain_pacemaker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ namespace eosio::chain {
if (_active_finalizer_policy.generation == 0) {
ilog("Switching to instant finality at block ${b}", ("b", block->block_num()));
// switching from dpos to hotstuff, all nodes will switch at same block height
// block header extension is set in finalize_block to value set by host function set_finalizers
// block header extension is set in finish_block to value set by host function set_finalizers
_chain->set_hs_irreversible_block_num(block->block_num()); // can be any value <= dpos lib
}
auto if_extension = std::get<instant_finality_extension>(*ext);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ struct pending_block_header_state_legacy : public detail::block_header_state_leg
* start_block -> (global_property_object.proposed_schedule_block_num == dpos_lib)
* building_block._new_pending_producer_schedule = producers
*
* finalize_block ->
* finish_block ->
* block_header.extensions.wtmsig_block_signatures = producers
* block_header.new_producers = producers
*
Expand Down
6 changes: 5 additions & 1 deletion libraries/chain/include/eosio/chain/block_state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@

namespace eosio::chain {

struct block_state_legacy;

struct block_state : public block_header_state { // block_header_state provides parent link
// ------ data members -------------------------------------------------------------
signed_block_ptr block;
bool validated; // We have executed the block's trxs and verified that action merkle root (block id) matches.
bool validated = false; // We have executed the block's trxs and verified that action merkle root (block id) matches.
digest_type strong_digest; // finalizer_digest (strong, cached so we can quickly validate votes)
digest_type weak_digest; // finalizer_digest (weak, cached so we can quickly validate votes)
pending_quorum_certificate pending_qc; // where we accumulate votes we receive
Expand Down Expand Up @@ -47,6 +49,8 @@ struct block_state : public block_header_state { // block_header_state provi

block_state(const block_header_state& bhs, deque<transaction_metadata_ptr>&& trx_metas,
deque<transaction_receipt>&& trx_receipts);

explicit block_state(const block_state_legacy& bsp);
};

using block_state_ptr = std::shared_ptr<block_state>;
Expand Down
1 change: 1 addition & 0 deletions libraries/chain/include/eosio/chain/block_state_legacy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ namespace eosio::chain {
friend struct fc::reflector<block_state_legacy>;
friend struct controller_impl;
friend struct completed_block;
friend struct block_state;

bool is_pub_keys_recovered()const { return _pub_keys_recovered; }

Expand Down
49 changes: 22 additions & 27 deletions libraries/chain/include/eosio/chain/controller.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,23 +51,24 @@ namespace eosio::chain {
using resource_limits::resource_limits_manager;
using apply_handler = std::function<void(apply_context&)>;

template<class bsp>
using branch_type_t = fork_database<bsp>::branch_type;

using branch_type_legacy = branch_type_t<block_state_legacy_ptr>;
using branch_type = branch_type_t<block_state_ptr>;

template<class bsp>
using forked_branch_callback_t = std::function<void(const branch_type_t<bsp>&)>;

using forked_branch_callback_legacy = forked_branch_callback_t<block_state_legacy_ptr>;
using forked_branch_callback = forked_branch_callback_t<block_state_ptr>;
using forked_callback_t = std::function<void(const transaction_metadata_ptr&)>;

// lookup transaction_metadata via supplied function to avoid re-creation
using trx_meta_cache_lookup = std::function<transaction_metadata_ptr( const transaction_id_type&)>;

using block_signal_params = std::tuple<const signed_block_ptr&, const block_id_type&>;

// Created via create_block_token(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_token {
std::variant<block_state_legacy_ptr, block_state_ptr> 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,
Expand Down Expand Up @@ -183,29 +184,25 @@ namespace eosio::chain {
fc::microseconds total_time{};
};

void finalize_block( block_report& br, const signer_callback_type& signer_callback );
void finish_block( block_report& br, const signer_callback_type& signer_callback );
void sign_block( const signer_callback_type& signer_callback );
void commit_block();

// thread-safe
std::future<block_state_legacy_ptr> create_block_state_future( const block_id_type& id, const signed_block_ptr& b );
std::future<block_token> create_block_token_future( const block_id_type& id, const signed_block_ptr& b );
// thread-safe
block_state_legacy_ptr create_block_state( const block_id_type& id, const signed_block_ptr& b ) const;
// returns empty optional if block b is not immediately ready to be processed
std::optional<block_token> create_block_token( const block_id_type& id, const signed_block_ptr& b ) const;

/**
* @param br returns statistics for block
* @param bsp block to push
* @param bt block to push, created by create_block_token
* @param cb calls cb with forked applied transactions for each forked block
* @param trx_lookup user provided lookup function for externally cached transaction_metadata
*/
void push_block( block_report& br,
const block_state_legacy_ptr& bsp,
const forked_branch_callback_legacy& cb,
const trx_meta_cache_lookup& trx_lookup );

void push_block( block_report& br,
const block_state_ptr& bsp,
const forked_branch_callback& cb,
const block_token& bt,
const forked_callback_t& cb,
const trx_meta_cache_lookup& trx_lookup );

boost::asio::io_context& get_thread_pool();
Expand Down Expand Up @@ -284,13 +281,11 @@ namespace eosio::chain {
// thread-safe
signed_block_ptr fetch_block_by_id( const block_id_type& id )const;
// thread-safe
bool block_exists( const block_id_type& id)const;
// thread-safe
std::optional<signed_block_header> fetch_block_header_by_number( uint32_t block_num )const;
// thread-safe
std::optional<signed_block_header> fetch_block_header_by_id( const block_id_type& id )const;
// return block_state_legacy from forkdb, thread-safe
block_state_legacy_ptr fetch_block_state_by_number( uint32_t block_num )const;
// return block_state_legacy from forkdb, thread-safe
block_state_legacy_ptr fetch_block_state_by_id( block_id_type id )const;
// thread-safe
block_id_type get_block_id_for_num( uint32_t block_num )const;

Expand Down
2 changes: 2 additions & 0 deletions libraries/chain/include/eosio/chain/fork_database.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ namespace eosio::chain {
explicit fork_database( const std::filesystem::path& data_dir );
~fork_database();

std::filesystem::path get_data_dir() const;

void open( validator_t& validator );
void close();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,17 +133,9 @@ class unapplied_transaction_queue {
}
}

template<class BRANCH_TYPE>
void add_forked( const BRANCH_TYPE& forked_branch ) {
// forked_branch is in reverse order
for( auto ritr = forked_branch.rbegin(), rend = forked_branch.rend(); ritr != rend; ++ritr ) {
const auto& bsptr = *ritr;
for( auto itr = bsptr->trxs_metas().begin(), end = bsptr->trxs_metas().end(); itr != end; ++itr ) {
const auto& trx = *itr;
auto insert_itr = queue.insert( { trx, trx_enum_type::forked } );
if( insert_itr.second ) added( insert_itr.first );
}
}
void add_forked( const transaction_metadata_ptr& trx ) {
auto insert_itr = queue.insert( { trx, trx_enum_type::forked } );
if( insert_itr.second ) added( insert_itr.first );
}

void add_aborted( deque<transaction_metadata_ptr> aborted_trxs ) {
Expand Down
6 changes: 3 additions & 3 deletions libraries/chain/resource_limits.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ void resource_limits_manager::set_block_parameters(const elastic_limit_parameter
c.cpu_limit_parameters = cpu_limit_parameters;
c.net_limit_parameters = net_limit_parameters;

// set_block_parameters is called by controller::finalize_block,
// set_block_parameters is called by controller::finish_block,
// where transaction specific logging is not possible
if (auto dm_logger = _get_deep_mind_logger(false)) {
dm_logger->on_update_resource_limits_config(c);
Expand Down Expand Up @@ -359,7 +359,7 @@ void resource_limits_manager::process_account_limit_updates() {
multi_index.remove(*itr);
}

// process_account_limit_updates is called by controller::finalize_block,
// process_account_limit_updates is called by controller::finish_block,
// where transaction specific logging is not possible
if (auto dm_logger = _get_deep_mind_logger(false)) {
dm_logger->on_update_resource_limits_state(state);
Expand All @@ -381,7 +381,7 @@ void resource_limits_manager::process_block_usage(uint32_t block_num) {
state.update_virtual_net_limit(config);
state.pending_net_usage = 0;

// process_block_usage is called by controller::finalize_block,
// process_block_usage is called by controller::finish,
// where transaction specific logging is not possible
if (auto dm_logger = _get_deep_mind_logger(false)) {
dm_logger->on_update_resource_limits_state(state);
Expand Down
12 changes: 6 additions & 6 deletions libraries/testing/include/eosio/testing/tester.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -606,9 +606,9 @@ namespace eosio { namespace testing {

signed_block_ptr produce_block( fc::microseconds skip_time = fc::milliseconds(config::block_interval_ms) )override {
auto sb = _produce_block(skip_time, false);
auto bsf = validating_node->create_block_state_future( sb->calculate_id(), sb );
auto btf = validating_node->create_block_token_future( sb->calculate_id(), sb );
controller::block_report br;
validating_node->push_block( br, bsf.get(), {}, trx_meta_cache_lookup{} );
validating_node->push_block( br, btf.get(), {}, trx_meta_cache_lookup{} );

return sb;
}
Expand All @@ -618,17 +618,17 @@ namespace eosio { namespace testing {
}

void validate_push_block(const signed_block_ptr& sb) {
auto bsf = validating_node->create_block_state_future( sb->calculate_id(), sb );
auto btf = validating_node->create_block_token_future( sb->calculate_id(), sb );
controller::block_report br;
validating_node->push_block( br, bsf.get(), {}, trx_meta_cache_lookup{} );
validating_node->push_block( br, btf.get(), {}, trx_meta_cache_lookup{} );
}

signed_block_ptr produce_empty_block( fc::microseconds skip_time = fc::milliseconds(config::block_interval_ms) )override {
unapplied_transactions.add_aborted( control->abort_block() );
auto sb = _produce_block(skip_time, true);
auto bsf = validating_node->create_block_state_future( sb->calculate_id(), sb );
auto btf = validating_node->create_block_token_future( sb->calculate_id(), sb );
controller::block_report br;
validating_node->push_block( br, bsf.get(), {}, trx_meta_cache_lookup{} );
validating_node->push_block( br, btf.get(), {}, trx_meta_cache_lookup{} );

return sb;
}
Expand Down
12 changes: 6 additions & 6 deletions libraries/testing/tester.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -376,11 +376,11 @@ namespace eosio { namespace testing {
}

void base_tester::push_block(signed_block_ptr b) {
auto bsf = control->create_block_state_future(b->calculate_id(), b);
auto btf = control->create_block_token_future(b->calculate_id(), b);
unapplied_transactions.add_aborted( control->abort_block() );
controller::block_report br;
control->push_block( br, bsf.get(), [this]( const branch_type_legacy& forked_branch ) {
unapplied_transactions.add_forked( forked_branch );
control->push_block( br, btf.get(), [this]( const transaction_metadata_ptr& trx ) {
unapplied_transactions.add_forked( trx );
}, [this]( const transaction_id_type& id ) {
return unapplied_transactions.get_trx( id );
} );
Expand Down Expand Up @@ -487,7 +487,7 @@ namespace eosio { namespace testing {
});

controller::block_report br;
control->finalize_block( br, [&]( digest_type d ) {
control->finish_block( br, [&]( digest_type d ) {
std::vector<signature_type> result;
result.reserve(signing_keys.size());
for (const auto& k: signing_keys)
Expand Down Expand Up @@ -1115,10 +1115,10 @@ namespace eosio { namespace testing {

auto block = a.control->fetch_block_by_number(i);
if( block ) { //&& !b.control->is_known_block(block->id()) ) {
auto bsf = b.control->create_block_state_future( block->calculate_id(), block );
auto btf = b.control->create_block_token_future( block->calculate_id(), block );
b.control->abort_block();
controller::block_report br;
b.control->push_block(br, bsf.get(), {}, trx_meta_cache_lookup{}); //, eosio::chain::validation_steps::created_block);
b.control->push_block(br, btf.get(), {}, trx_meta_cache_lookup{}); //, eosio::chain::validation_steps::created_block);
}
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ namespace eosio::chain::plugin_interface {
namespace incoming {
namespace methods {
// synchronously push a block/trx to a single provider, block_state_legacy_ptr may be null
using block_sync = method_decl<chain_plugin_interface, bool(const signed_block_ptr&, const std::optional<block_id_type>&, const block_state_legacy_ptr&), first_provider_policy>;
using block_sync = method_decl<chain_plugin_interface, bool(const signed_block_ptr&, const std::optional<block_id_type>&, const std::optional<block_token>&), first_provider_policy>;
using transaction_async = method_decl<chain_plugin_interface, void(const packed_transaction_ptr&, bool, transaction_metadata::trx_type, bool, next_function<transaction_trace_ptr>), first_provider_policy>;
}
}
Expand Down
Loading