Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/hotstuff_integration' into GH-2125
Browse files Browse the repository at this point in the history
…-consider-vote
  • Loading branch information
heifner committed Mar 11, 2024
2 parents cac3bf7 + 12f21e9 commit b267c37
Show file tree
Hide file tree
Showing 24 changed files with 487 additions and 227 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,4 @@ node_modules
package-lock.json

snapshots
!unittests/snapshots
53 changes: 37 additions & 16 deletions libraries/chain/block_header_state_legacy.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include <eosio/chain/block_header_state_legacy.hpp>
#include <eosio/chain/block_header_state_utils.hpp>
#include <eosio/chain/snapshot_detail.hpp>
#include <eosio/chain/exceptions.hpp>
#include <limits>

Expand Down Expand Up @@ -438,23 +439,43 @@ namespace eosio::chain {
return detail::get_new_protocol_feature_activations(header_exts);
}

block_header_state_legacy::block_header_state_legacy( legacy::snapshot_block_header_state_v2&& snapshot )
block_header_state_legacy::block_header_state_legacy( snapshot_detail::snapshot_block_header_state_legacy_v2&& bhs_v2 )
{
block_num = snapshot.block_num;
dpos_proposed_irreversible_blocknum = snapshot.dpos_proposed_irreversible_blocknum;
dpos_irreversible_blocknum = snapshot.dpos_irreversible_blocknum;
active_schedule = producer_authority_schedule( snapshot.active_schedule );
blockroot_merkle = std::move(snapshot.blockroot_merkle);
producer_to_last_produced = std::move(snapshot.producer_to_last_produced);
producer_to_last_implied_irb = std::move(snapshot.producer_to_last_implied_irb);
valid_block_signing_authority = block_signing_authority_v0{ 1, {{std::move(snapshot.block_signing_key), 1}} };
confirm_count = std::move(snapshot.confirm_count);
id = snapshot.id;
header = std::move(snapshot.header);
pending_schedule.schedule_lib_num = snapshot.pending_schedule.schedule_lib_num;
pending_schedule.schedule_hash = snapshot.pending_schedule.schedule_hash;
pending_schedule.schedule = producer_authority_schedule( snapshot.pending_schedule.schedule );
activated_protocol_features = std::move(snapshot.activated_protocol_features);
block_num = bhs_v2.block_num;
dpos_proposed_irreversible_blocknum = bhs_v2.dpos_proposed_irreversible_blocknum;
dpos_irreversible_blocknum = bhs_v2.dpos_irreversible_blocknum;
active_schedule = producer_authority_schedule( bhs_v2.active_schedule );
blockroot_merkle = std::move(bhs_v2.blockroot_merkle);
producer_to_last_produced = std::move(bhs_v2.producer_to_last_produced);
producer_to_last_implied_irb = std::move(bhs_v2.producer_to_last_implied_irb);
valid_block_signing_authority = block_signing_authority_v0{ 1, {{std::move(bhs_v2.block_signing_key), 1}} };
confirm_count = std::move(bhs_v2.confirm_count);
id = bhs_v2.id;
header = std::move(bhs_v2.header);
pending_schedule.schedule_lib_num = bhs_v2.pending_schedule.schedule_lib_num;
pending_schedule.schedule_hash = bhs_v2.pending_schedule.schedule_hash;
pending_schedule.schedule = producer_authority_schedule( bhs_v2.pending_schedule.schedule );
activated_protocol_features = std::move(bhs_v2.activated_protocol_features);
}

block_header_state_legacy::block_header_state_legacy( snapshot_detail::snapshot_block_header_state_legacy_v3&& bhs_v3 )
{
block_num = bhs_v3.block_num;
dpos_proposed_irreversible_blocknum = bhs_v3.dpos_proposed_irreversible_blocknum;
dpos_irreversible_blocknum = bhs_v3.dpos_irreversible_blocknum;
active_schedule = std::move(bhs_v3.active_schedule);
blockroot_merkle = std::move(bhs_v3.blockroot_merkle);
producer_to_last_produced = std::move(bhs_v3.producer_to_last_produced);
producer_to_last_implied_irb = std::move(bhs_v3.producer_to_last_implied_irb);
valid_block_signing_authority = std::move(bhs_v3.valid_block_signing_authority);
confirm_count = std::move(bhs_v3.confirm_count);
id = bhs_v3.id;
header = std::move(bhs_v3.header);
pending_schedule = std::move(bhs_v3.pending_schedule);
activated_protocol_features = std::move(bhs_v3.activated_protocol_features);
additional_signatures = std::move(bhs_v3.additional_signatures);

header_exts = header.validate_and_extract_header_extensions();
}


Expand Down
23 changes: 23 additions & 0 deletions libraries/chain/block_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <eosio/chain/block_header_state_utils.hpp>
#include <eosio/chain/block_state_legacy.hpp>
#include <eosio/chain/hotstuff/finalizer.hpp>
#include <eosio/chain/snapshot_detail.hpp>
#include <eosio/chain/exceptions.hpp>

#include <fc/crypto/bls_utils.hpp>
Expand Down Expand Up @@ -71,6 +72,28 @@ block_state::block_state(const block_state_legacy& bsp) {
cached_trxs = bsp._cached_trxs;
}

block_state::block_state(snapshot_detail::snapshot_block_state_v7&& sbs)
: block_header_state {
.block_id = sbs.block_id,
.header = std::move(sbs.header),
.activated_protocol_features = std::move(sbs.activated_protocol_features),
.core = std::move(sbs.core),
.proposal_mtree = std::move(sbs.proposal_mtree),
.finality_mtree = std::move(sbs.finality_mtree),
.active_finalizer_policy = std::move(sbs.active_finalizer_policy),
.active_proposer_policy = std::move(sbs.active_proposer_policy),
.proposer_policies = std::move(sbs.proposer_policies),
.finalizer_policies = std::move(sbs.finalizer_policies)
}
, strong_digest(compute_finalizer_digest())
, weak_digest(create_weak_digest(strong_digest))
, pending_qc(active_finalizer_policy->finalizers.size(), active_finalizer_policy->threshold,
active_finalizer_policy->max_weak_sum_before_weak_final()) // just in case we receive votes
// , valid(std::move(sbs.valid) // [snapshot todo]
{
header_exts = header.validate_and_extract_header_extensions();
}

deque<transaction_metadata_ptr> block_state::extract_trxs_metas() {
pub_keys_recovered = false;
auto result = std::move(cached_trxs);
Expand Down
14 changes: 11 additions & 3 deletions libraries/chain/block_state_legacy.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#include <eosio/chain/block_state_legacy.hpp>
#include <eosio/chain/block_header_state_utils.hpp>
#include <eosio/chain/exceptions.hpp>
#include <eosio/chain/snapshot_detail.hpp>

namespace eosio { namespace chain {

namespace eosio::chain {

namespace {
constexpr auto additional_sigs_eid = additional_block_signatures_extension::extension_id();
Expand Down Expand Up @@ -58,7 +60,7 @@ namespace eosio { namespace chain {
bool skip_validate_signee
)
:block_header_state_legacy( prev.next( *b, detail::extract_additional_signatures(b), pfs, validator, skip_validate_signee ) )
,block( std::move(b) )
,block( std::move(b) )
{}

block_state_legacy::block_state_legacy( pending_block_header_state_legacy&& cur,
Expand All @@ -74,4 +76,10 @@ namespace eosio { namespace chain {
,_cached_trxs( std::move(trx_metas) )
{}

} } /// eosio::chain
block_state_legacy::block_state_legacy(snapshot_detail::snapshot_block_state_legacy_v7&& sbs)
: block_header_state_legacy(std::move(static_cast<snapshot_detail::snapshot_block_header_state_legacy_v3&>(sbs)))
// , valid(std::move(sbs.valid) // [snapshot todo]
{
}

} /// eosio::chain
102 changes: 62 additions & 40 deletions libraries/chain/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <eosio/chain/resource_limits.hpp>
#include <eosio/chain/subjective_billing.hpp>
#include <eosio/chain/chain_snapshot.hpp>
#include <eosio/chain/snapshot_detail.hpp>
#include <eosio/chain/thread_utils.hpp>
#include <eosio/chain/platform_timer.hpp>
#include <eosio/chain/block_header_state_utils.hpp>
Expand Down Expand Up @@ -869,7 +870,7 @@ struct controller_impl {
named_thread_pool<chain> thread_pool;
deep_mind_handler* deep_mind_logger = nullptr;
bool okay_to_print_integrity_hash_on_stop = false;
my_finalizers_t my_finalizers;
my_finalizers_t my_finalizers;
std::atomic<bool> writing_snapshot = false;

thread_local static platform_timer timer; // a copy for main thread and each read-only thread
Expand Down Expand Up @@ -1634,19 +1635,17 @@ struct controller_impl {
// Also, even though blog.head() may still be nullptr, blog.first_block_num() is guaranteed to be lib_num + 1.

auto finish_init = [&](auto& forkdb) {
if( read_mode != db_read_mode::IRREVERSIBLE
&& forkdb.pending_head()->id() != forkdb.head()->id()
&& forkdb.head()->id() == forkdb.root()->id()
) {
wlog( "read_mode has changed from irreversible: applying best branch from fork database" );

for( auto pending_head = forkdb.pending_head();
pending_head->id() != forkdb.head()->id();
pending_head = forkdb.pending_head()
) {
wlog( "applying branch from fork database ending with block: ${id}", ("id", pending_head->id()) );
controller::block_report br;
maybe_switch_forks( br, pending_head, controller::block_status::complete, {}, trx_meta_cache_lookup{} );
if( read_mode != db_read_mode::IRREVERSIBLE ) {
auto pending_head = forkdb.pending_head();
auto head = forkdb.head();
if ( head && pending_head && pending_head->id() != head->id() && head->id() == forkdb.root()->id() ) {
wlog( "read_mode has changed from irreversible: applying best branch from fork database" );

for( ; pending_head->id() != forkdb.head()->id(); pending_head = forkdb.pending_head() ) {
wlog( "applying branch from fork database ending with block: ${id}", ("id", pending_head->id()) );
controller::block_report br;
maybe_switch_forks( br, pending_head, controller::block_status::complete, {}, trx_meta_cache_lookup{} );
}
}
}
};
Expand Down Expand Up @@ -1772,12 +1771,12 @@ struct controller_impl {
section.add_row(chain_snapshot_header(), db);
});

#warning todo: add snapshot support for new (IF) block_state section
apply<void>(chain_head, [&](const auto& head) {
if constexpr (std::is_same_v<block_state_legacy_ptr, typename std::decay_t<decltype(head)>>)
snapshot->write_section("eosio::chain::block_state", [&]( auto& section ) {
section.template add_row<block_header_state_legacy>(*head, db);
});
snapshot_detail::snapshot_block_state_variant_v7 block_state_variant(*head);

snapshot->write_section("eosio::chain::block_state", [&]( auto& section ) {
section.add_row(block_state_variant, db);
});
});

controller_index_set::walk_indices([this, &snapshot]( auto utils ){
Expand Down Expand Up @@ -1826,53 +1825,76 @@ struct controller_impl {
header.validate();
});

#warning todo: add snapshot support for new (IF) block_state section
auto read_block_state_section = [&](auto& forkdb) { /// load and upgrade the block header state
block_header_state_legacy head_header_state;
using v2 = legacy::snapshot_block_header_state_v2;

if (std::clamp(header.version, v2::minimum_version, v2::maximum_version) == header.version ) {
snapshot->read_section("eosio::chain::block_state", [this, &head_header_state]( auto &section ) {
legacy::snapshot_block_header_state_v2 legacy_header_state;
section.read_row(legacy_header_state, db);
head_header_state = block_header_state_legacy(std::move(legacy_header_state));
});
using namespace snapshot_detail;
using v7 = snapshot_block_state_variant_v7;

if (header.version >= v7::minimum_version) {
// loading a snapshot saved by Leap 6.0 and above.
// -----------------------------------------------
if (std::clamp(header.version, v7::minimum_version, v7::maximum_version) == header.version ) {
snapshot->read_section("eosio::chain::block_state", [this]( auto &section ){
v7 block_state_variant;
section.read_row(block_state_variant, db);
std::visit(overloaded{
[&](snapshot_block_state_legacy_v7&& sbs) { chain_head = block_handle{std::make_shared<block_state_legacy>(std::move(sbs))}; },
[&](snapshot_block_state_v7&& sbs) { chain_head = block_handle{std::make_shared<block_state>(std::move(sbs))}; }},
std::move(block_state_variant.v));
});
} else {
EOS_THROW(snapshot_exception, "Unsupported block_state version");
}
} else {
snapshot->read_section("eosio::chain::block_state", [this,&head_header_state]( auto &section ){
section.read_row(head_header_state, db);
});
// loading a snapshot saved by Leap up to version 5.
// -------------------------------------------------
auto head_header_state = std::make_shared<block_state_legacy>();
using v2 = snapshot_block_header_state_legacy_v2;
using v3 = snapshot_block_header_state_legacy_v3;

if (std::clamp(header.version, v2::minimum_version, v2::maximum_version) == header.version ) {
snapshot->read_section("eosio::chain::block_state", [this, &head_header_state]( auto &section ) {
v2 legacy_header_state;
section.read_row(legacy_header_state, db);
static_cast<block_header_state_legacy&>(*head_header_state) = block_header_state_legacy(std::move(legacy_header_state));
});
} else if (std::clamp(header.version, v3::minimum_version, v3::maximum_version) == header.version ) {
snapshot->read_section("eosio::chain::block_state", [this,&head_header_state]( auto &section ){
v3 legacy_header_state;
section.read_row(legacy_header_state, db);
static_cast<block_header_state_legacy&>(*head_header_state) = block_header_state_legacy(std::move(legacy_header_state));
});
} else {
EOS_THROW(snapshot_exception, "Unsupported block_header_state version");
}
chain_head = block_handle{head_header_state};
}

snapshot_head_block = head_header_state.block_num;
snapshot_head_block = chain_head.block_num();
EOS_ASSERT( blog_start <= (snapshot_head_block + 1) && snapshot_head_block <= blog_end,
block_log_exception,
"Block log is provided with snapshot but does not contain the head block from the snapshot nor a block right after it",
("snapshot_head_block", snapshot_head_block)
("block_log_first_num", blog_start)
("block_log_last_num", blog_end)
);

auto head = std::make_shared<block_state_legacy>();
chain_head = block_handle{head};
static_cast<block_header_state_legacy&>(*head) = head_header_state;
};
fork_db.apply_l<void>(read_block_state_section);

controller_index_set::walk_indices([this, &snapshot, &header]( auto utils ){
using value_t = typename decltype(utils)::index_t::value_type;

// skip the table_id_object as its inlined with contract tables section
if (std::is_same<value_t, table_id_object>::value) {
if (std::is_same_v<value_t, table_id_object>) {
return;
}

// skip the database_header as it is only relevant to in-memory database
if (std::is_same<value_t, database_header_object>::value) {
if (std::is_same_v<value_t, database_header_object>) {
return;
}

// special case for in-place upgrade of global_property_object
if (std::is_same<value_t, global_property_object>::value) {
if (std::is_same_v<value_t, global_property_object>) {
using v2 = legacy::snapshot_global_property_object_v2;
using v3 = legacy::snapshot_global_property_object_v3;
using v4 = legacy::snapshot_global_property_object_v4;
Expand Down
2 changes: 1 addition & 1 deletion libraries/chain/fork_database.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,9 @@ namespace eosio::chain {
>;

std::mutex mtx;
fork_multi_index_type index;
bsp_t root;
bsp_t head;
fork_multi_index_type index;
const uint32_t magic_number;

explicit fork_database_impl(uint32_t magic_number) : magic_number(magic_number) {}
Expand Down
4 changes: 4 additions & 0 deletions libraries/chain/include/eosio/chain/block_header_state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@

namespace eosio::chain {

namespace snapshot_detail {
struct snapshot_block_state_v7;
}

namespace detail { struct schedule_info; };

struct building_block_input {
Expand Down
Loading

0 comments on commit b267c37

Please sign in to comment.