Skip to content

Commit

Permalink
GH-1523 WIP: adding proposed finalizer_set to block_header_state and …
Browse files Browse the repository at this point in the history
…block_header extension.
  • Loading branch information
heifner committed Sep 1, 2023
1 parent 060b5ba commit 07e05f0
Show file tree
Hide file tree
Showing 10 changed files with 86 additions and 32 deletions.
25 changes: 25 additions & 0 deletions libraries/chain/block_header.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <eosio/chain/block.hpp>
#include <eosio/chain/finalizer_authority.hpp>
#include <eosio/chain/merkle.hpp>
#include <fc/io/raw.hpp>
#include <fc/bitutil.hpp>
Expand Down Expand Up @@ -64,4 +65,28 @@ namespace eosio { namespace chain {
return results;
}

std::optional<block_header_extension> block_header::extract_header_extension(uint16_t extension_id)const {
using decompose_t = block_header_extension_types::decompose_t;

for( size_t i = 0; i < header_extensions.size(); ++i ) {
const auto& e = header_extensions[i];
auto id = e.first;

if (id != extension_id)
continue;

block_header_extension ext;

auto match = decompose_t::extract<block_header_extension>( id, e.second, ext );
EOS_ASSERT( match, invalid_block_header_extension,
"Block header extension with id type ${id} is not supported",
("id", id)
);

return ext;
}

return {};
}

} }
1 change: 1 addition & 0 deletions libraries/chain/block_header_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ namespace eosio { namespace chain {

result.valid_block_signing_authority = proauth.authority;
result.producer = proauth.producer_name;
result.last_proposed_finalizer_set_generation = last_proposed_finalizer_set_generation;

result.blockroot_merkle = blockroot_merkle;
result.blockroot_merkle.append( id );
Expand Down
30 changes: 20 additions & 10 deletions libraries/chain/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <eosio/chain/deep_mind.hpp>
#include <eosio/chain/wasm_interface_collection.hpp>
#include <eosio/chain/finalizer_set.hpp>
#include <eosio/chain/finalizer_authority.hpp>

#include <chainbase/chainbase.hpp>
#include <eosio/vm/allocator.hpp>
Expand Down Expand Up @@ -1904,6 +1905,18 @@ struct controller_impl {

block_ptr->transactions = std::move( bb._pending_trx_receipts );

if (bb._pending_block_header_state.proposed_finalizer_set) {
// proposed_finalizer_set can't be set until builtin_protocol_feature_t::instant_finality activated
finalizer_set& fin_set = *bb._pending_block_header_state.proposed_finalizer_set;
++bb._pending_block_header_state.last_proposed_finalizer_set_generation;
fin_set.generation = bb._pending_block_header_state.last_proposed_finalizer_set_generation;
emplace_extension(
block_ptr->header_extensions,
hs_finalizer_set_extension::extension_id(),
fc::raw::pack( hs_finalizer_set_extension{ std::move(fin_set) } )
);
}

auto id = block_ptr->calculate_id();

// Update TaPoS table:
Expand Down Expand Up @@ -1977,10 +1990,11 @@ struct controller_impl {
pending->push();
}

void set_finalizers_impl(const finalizer_set& fin_set) {
// TODO store in chainbase
current_finalizer_set = fin_set;
++current_finalizer_set.generation;
void set_proposed_finalizers(const finalizer_set& fin_set) {
assert(pending); // has to exist and be building_block since called from host function
auto& bb = std::get<building_block>(pending->_block_stage);

bb._pending_block_header_state.proposed_finalizer_set.emplace(fin_set);
}

/**
Expand Down Expand Up @@ -3290,12 +3304,8 @@ int64_t controller::set_proposed_producers( vector<producer_authority> producers
return version;
}

void controller::set_finalizers( const finalizer_set& fin_set ) {
my->set_finalizers_impl(fin_set);
}

const finalizer_set& controller::get_finalizers() const {
return my->current_finalizer_set;
void controller::set_proposed_finalizers( const finalizer_set& fin_set ) {
my->set_proposed_finalizers(fin_set);
}

const producer_authority_schedule& controller::active_producers()const {
Expand Down
7 changes: 7 additions & 0 deletions libraries/chain/include/eosio/chain/abi_serializer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -676,6 +676,13 @@ namespace impl {
std::get<producer_schedule_change_extension>(header_exts.lower_bound(producer_schedule_change_extension::extension_id())->second);
mvo("new_producer_schedule", new_producer_schedule);
}
if (header_exts.count(hs_finalizer_set_extension::extension_id())) {
// TODO: Will not compile without including finalizer_authority.hpp which includes bls12-381.
// Should we store the bls_public_key in compressed form?
// const auto& finalizer_set_extension =
// std::get<hs_finalizer_set_extension>(header_exts.lower_bound(hs_finalizer_set_extension::extension_id())->second);
// mvo("proposed_finalizer_set", finalizer_set_extension);
}

mvo("producer_signature", block.producer_signature);
add(mvo, "transactions", block.transactions, resolver, ctx);
Expand Down
6 changes: 5 additions & 1 deletion libraries/chain/include/eosio/chain/block_header.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
#include <eosio/chain/block_timestamp.hpp>
#include <eosio/chain/producer_schedule.hpp>
#include <eosio/chain/protocol_feature_activation.hpp>
#include <eosio/chain/finalizer_set.hpp>

#include <optional>
#include <type_traits>

namespace eosio { namespace chain {
Expand All @@ -17,7 +19,8 @@ namespace eosio { namespace chain {

using block_header_extension_types = detail::block_header_extension_types<
protocol_feature_activation,
producer_schedule_change_extension
producer_schedule_change_extension,
hs_finalizer_set_extension
>;

using block_header_extension = block_header_extension_types::block_header_extension_t;
Expand Down Expand Up @@ -68,6 +71,7 @@ namespace eosio { namespace chain {
static uint32_t num_from_id(const block_id_type& id);

flat_multimap<uint16_t, block_header_extension> validate_and_extract_header_extensions()const;
std::optional<block_header_extension> extract_header_extension(uint16_t extension_id)const;
};


Expand Down
5 changes: 4 additions & 1 deletion libraries/chain/include/eosio/chain/block_header_state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <eosio/chain/block_header.hpp>
#include <eosio/chain/incremental_merkle.hpp>
#include <eosio/chain/protocol_feature_manager.hpp>
#include <eosio/chain/finalizer_set.hpp>
#include <eosio/chain/chain_snapshot.hpp>
#include <future>

Expand Down Expand Up @@ -53,6 +54,7 @@ namespace detail {
uint32_t dpos_proposed_irreversible_blocknum = 0;
uint32_t dpos_irreversible_blocknum = 0;
producer_authority_schedule active_schedule;
uint32_t last_proposed_finalizer_set_generation = 0; // TODO: Add to snapshot_block_header_state_v3
incremental_merkle blockroot_merkle;
flat_map<account_name,uint32_t> producer_to_last_produced;
flat_map<account_name,uint32_t> producer_to_last_implied_irb;
Expand All @@ -74,6 +76,7 @@ namespace detail {
struct pending_block_header_state : public detail::block_header_state_common {
protocol_feature_activation_set_ptr prev_activated_protocol_features;
detail::schedule_info prev_pending_schedule;
std::optional<finalizer_set> proposed_finalizer_set; // set by set_finalizer host function
bool was_pending_promoted = false;
block_id_type previous;
account_name producer;
Expand Down Expand Up @@ -143,7 +146,6 @@ struct block_header_state : public detail::block_header_state_common {
const vector<digest_type>& )>& validator,
bool skip_validate_signee = false )const;

bool has_pending_producers()const { return pending_schedule.schedule.producers.size(); }
uint32_t calc_dpos_last_irreversible( account_name producer_of_next_block )const;

producer_authority get_scheduled_producer( block_timestamp_type t )const;
Expand All @@ -164,6 +166,7 @@ FC_REFLECT( eosio::chain::detail::block_header_state_common,
(dpos_proposed_irreversible_blocknum)
(dpos_irreversible_blocknum)
(active_schedule)
(last_proposed_finalizer_set_generation)
(blockroot_merkle)
(producer_to_last_produced)
(producer_to_last_implied_irb)
Expand Down
4 changes: 2 additions & 2 deletions libraries/chain/include/eosio/chain/controller.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -293,8 +293,8 @@ namespace eosio { namespace chain {

int64_t set_proposed_producers( vector<producer_authority> producers );

void set_finalizers( const finalizer_set& fin_set );
const finalizer_set& get_finalizers() const;
// called by host function set_finalizers
void set_proposed_finalizers( const finalizer_set& fin_set );

bool light_validation_allowed() const;
bool skip_auth_check()const;
Expand Down
2 changes: 1 addition & 1 deletion libraries/chain/webassembly/privileged.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ namespace eosio { namespace chain { namespace webassembly {
EOS_ASSERT( finalizers.size() == unique_finalizer_keys.size(), wasm_execution_error, "Duplicate finalizer bls key in finalizer set" );
EOS_ASSERT( finset.fthreshold > f_weight_sum / 2, wasm_execution_error, "Finalizer set threshold cannot be met by finalizer weights" );

context.control.set_finalizers( finset );
context.control.set_proposed_finalizers( finset );
}

uint32_t interface::get_blockchain_parameters_packed( legacy_span<char> packed_blockchain_parameters ) const {
Expand Down
34 changes: 18 additions & 16 deletions libraries/hotstuff/chain_pacemaker.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <eosio/hotstuff/chain_pacemaker.hpp>
#include <eosio/chain/finalizer_authority.hpp>
#include <iostream>

// comment this out to remove the core profiler
Expand Down Expand Up @@ -108,6 +109,9 @@ namespace eosio { namespace hotstuff {
_accepted_block_connection = chain->accepted_block.connect( [this]( const block_state_ptr& blk ) {
on_accepted_block( blk );
} );
_irreversible_block_connection = chain->irreversible_block.connect( [this]( const block_state_ptr& blk ) {
on_irreversible_block( blk );
} );
_head_block_state = chain->head_block_state();
}

Expand Down Expand Up @@ -211,8 +215,17 @@ namespace eosio { namespace hotstuff {
void chain_pacemaker::on_accepted_block( const block_state_ptr& blk ) {
std::scoped_lock g( _chain_state_mutex );
_head_block_state = blk;
// TODO only update local cache if changed, check version or use !=
_finalizer_set = _chain->get_finalizers(); // TODO get from chainbase or from block_state
}

// called from main thread
void chain_pacemaker::on_irreversible_block( const block_state_ptr& blk ) {
if (!blk->block->header_extensions.empty()) {
std::optional<block_header_extension> ext = blk->block->extract_header_extension(hs_finalizer_set_extension::extension_id());
if (ext) {
std::scoped_lock g( _chain_state_mutex );
_active_finalizer_set = std::move(std::get<hs_finalizer_set_extension>(*ext));
}
}
}

name chain_pacemaker::get_proposer() {
Expand Down Expand Up @@ -246,21 +259,10 @@ namespace eosio { namespace hotstuff {

std::vector<name> chain_pacemaker::get_finalizers() {

#warning FIXME: Use new finalizer list in pacemaker/qc_chain.
// Every time qc_chain wants to know what the finalizers are, we get it from the controller, which
// is where it's currently stored.
//
// TODO:
// - solve threading. for this particular case, I don't think using _chain-> is a big deal really;
// set_finalizers is called once in a blue moon, and this could be solved by a simple mutex even
// if it is the main thread that is waiting for a lock. But maybe there's a better way to do this
// overall.
// - use this information in qc_chain and delete the old code below
// - list of string finalizer descriptions instead of eosio name now
// - also return the keys for each finalizer, not just name/description so qc_chain can use them
//
#warning FIXME: Use _active_finalizer_set in pacemaker/qc_chain.
// _active_finalizer_set should be used

std::unique_lock g( _chain_state_mutex );
const auto& fin_set = _chain->get_finalizers(); // TODO use
block_state_ptr hbs = _head_block_state;
g.unlock();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ namespace eosio::hotstuff {

private:
void on_accepted_block( const block_state_ptr& blk );
void on_irreversible_block( const block_state_ptr& blk );

void on_hs_proposal_msg(const hs_proposal_message& msg); //consensus msg event handler
void on_hs_vote_msg(const hs_vote_message& msg); //confirmation msg event handler
Expand Down Expand Up @@ -74,9 +75,10 @@ namespace eosio::hotstuff {

mutable std::mutex _chain_state_mutex;
block_state_ptr _head_block_state;
finalizer_set _finalizer_set;
finalizer_set _active_finalizer_set;

boost::signals2::scoped_connection _accepted_block_connection;
boost::signals2::scoped_connection _irreversible_block_connection;

qc_chain _qc_chain;
std::function<void(const chain::hs_message&)> bcast_hs_message;
Expand Down

0 comments on commit 07e05f0

Please sign in to comment.