Skip to content
This repository has been archived by the owner on Aug 2, 2022. It is now read-only.

Commit

Permalink
reduce duplication in block header state structs (addresses review co…
Browse files Browse the repository at this point in the history
…mments)
  • Loading branch information
arhag committed Jan 17, 2019
1 parent 2cb4dbc commit be795a8
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 96 deletions.
43 changes: 16 additions & 27 deletions libraries/chain/block_header_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,13 +109,11 @@ namespace eosio { namespace chain {
result.dpos_irreversible_blocknum = calc_dpos_last_irreversible( prokey.producer_name );

result.prev_pending_schedule = pending_schedule;
result.prev_pending_schedule_lib_num = pending_schedule_lib_num;
result.prev_pending_schedule_hash = pending_schedule_hash;

if( pending_schedule.producers.size() &&
result.dpos_irreversible_blocknum >= pending_schedule_lib_num )
if( pending_schedule.schedule.producers.size() &&
result.dpos_irreversible_blocknum >= pending_schedule.schedule_lib_num )
{
result.active_schedule = pending_schedule;
result.active_schedule = pending_schedule.schedule;

flat_map<account_name,uint32_t> new_producer_to_last_produced;

Expand Down Expand Up @@ -194,40 +192,31 @@ namespace eosio { namespace chain {
if( h.new_producers ) {
EOS_ASSERT( !was_pending_promoted, producer_schedule_exception, "cannot set pending producer schedule in the same block in which pending was promoted to active" );
EOS_ASSERT( h.new_producers->version == active_schedule.version + 1, producer_schedule_exception, "wrong producer schedule version specified" );
EOS_ASSERT( prev_pending_schedule.producers.size() == 0, producer_schedule_exception,
EOS_ASSERT( prev_pending_schedule.schedule.producers.size() == 0, producer_schedule_exception,
"cannot set new pending producers until last pending is confirmed" );
}

block_header_state result;
auto block_number = block_num;

result.id = h.id();
result.block_num = block_num;
result.header = h;
block_header_state result( std::move( *static_cast<detail::block_header_state_common*>(this) ) );

result.dpos_proposed_irreversible_blocknum = dpos_proposed_irreversible_blocknum;
result.dpos_irreversible_blocknum = dpos_irreversible_blocknum;
result.id = h.id();
result.header = h;

if( h.new_producers ) {
result.pending_schedule = *h.new_producers;
result.pending_schedule_hash = digest_type::hash( result.pending_schedule );
result.pending_schedule_lib_num = block_num;
result.pending_schedule.schedule = *h.new_producers;
result.pending_schedule.schedule_hash = digest_type::hash( result.pending_schedule );
result.pending_schedule.schedule_lib_num = block_number;
} else {
if( was_pending_promoted ) {
result.pending_schedule.version = prev_pending_schedule.version;
result.pending_schedule.schedule.version = prev_pending_schedule.schedule.version;
} else {
result.pending_schedule = prev_pending_schedule;
result.pending_schedule.schedule = std::move( prev_pending_schedule.schedule );
}
result.pending_schedule_hash = std::move(prev_pending_schedule_hash);
result.pending_schedule_lib_num = prev_pending_schedule_lib_num;
result.pending_schedule.schedule_hash = std::move( prev_pending_schedule.schedule_hash );
result.pending_schedule.schedule_lib_num = prev_pending_schedule.schedule_lib_num;
}

result.active_schedule = std::move(active_schedule);
result.blockroot_merkle = std::move(blockroot_merkle);
result.producer_to_last_produced = std::move(producer_to_last_produced);
result.producer_to_last_implied_irb = std::move(producer_to_last_implied_irb);
result.block_signing_key = std::move(block_signing_key);
result.confirm_count = std::move(confirm_count);

return result;
}

Expand Down Expand Up @@ -267,7 +256,7 @@ namespace eosio { namespace chain {

digest_type block_header_state::sig_digest()const {
auto header_bmroot = digest_type::hash( std::make_pair( header.digest(), blockroot_merkle.get_root() ) );
return digest_type::hash( std::make_pair(header_bmroot, pending_schedule_hash) );
return digest_type::hash( std::make_pair(header_bmroot, pending_schedule.schedule_hash) );
}

void block_header_state::sign( const std::function<signature_type(const digest_type&)>& signer ) {
Expand Down
24 changes: 12 additions & 12 deletions libraries/chain/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -637,13 +637,13 @@ struct controller_impl {
producer_schedule_type initial_schedule{ 0, {{config::system_account_name, conf.genesis.initial_key}} };

block_header_state genheader;
genheader.active_schedule = initial_schedule;
genheader.pending_schedule = initial_schedule;
genheader.pending_schedule_hash = fc::sha256::hash(initial_schedule);
genheader.header.timestamp = conf.genesis.initial_timestamp;
genheader.header.action_mroot = conf.genesis.compute_chain_id();
genheader.id = genheader.header.id();
genheader.block_num = genheader.header.block_num();
genheader.active_schedule = initial_schedule;
genheader.pending_schedule.schedule = initial_schedule;
genheader.pending_schedule.schedule_hash = fc::sha256::hash(initial_schedule);
genheader.header.timestamp = conf.genesis.initial_timestamp;
genheader.header.action_mroot = conf.genesis.compute_chain_id();
genheader.id = genheader.header.id();
genheader.block_num = genheader.header.block_num();

head = std::make_shared<block_state>();
static_cast<block_header_state&>(*head) = genheader;
Expand Down Expand Up @@ -1148,7 +1148,7 @@ struct controller_impl {
const auto& gpo = db.get<global_property_object>();
if( gpo.proposed_schedule_block_num.valid() && // if there is a proposed schedule that was proposed in a block ...
( *gpo.proposed_schedule_block_num <= pbhs.dpos_irreversible_blocknum ) && // ... that has now become irreversible ...
pbhs.prev_pending_schedule.producers.size() == 0 // ... and there was room for a new pending schedule prior to any possible promotion
pbhs.prev_pending_schedule.schedule.producers.size() == 0 // ... and there was room for a new pending schedule prior to any possible promotion
)
{
// Promote proposed schedule to pending schedule.
Expand Down Expand Up @@ -1990,7 +1990,7 @@ const vector<transaction_receipt>& controller::get_pending_trx_receipts()const {
}

uint32_t controller::last_irreversible_block_num() const {
return std::max(std::max(my->head->bft_irreversible_blocknum, my->head->dpos_irreversible_blocknum), my->snapshot_head_block);
return std::max( my->head->dpos_irreversible_blocknum, my->snapshot_head_block);
}

block_id_type controller::last_irreversible_block_id() const {
Expand Down Expand Up @@ -2124,10 +2124,10 @@ const producer_schedule_type& controller::active_producers()const {

const producer_schedule_type& controller::pending_producers()const {
if( !(my->pending) )
return my->head->pending_schedule;
return my->head->pending_schedule.schedule;

if( my->pending->_block_stage.contains<completed_block>() )
return my->pending->_block_stage.get<completed_block>()._block_state->pending_schedule;
return my->pending->_block_stage.get<completed_block>()._block_state->pending_schedule.schedule;

if( my->pending->_block_stage.contains<assembled_block>() ) {
const auto& np = my->pending->_block_stage.get<assembled_block>()._unsigned_block->new_producers;
Expand All @@ -2140,7 +2140,7 @@ const producer_schedule_type& controller::pending_producers()const {
if( bb._new_pending_producer_schedule )
return *bb._new_pending_producer_schedule;

return bb._pending_block_header_state.prev_pending_schedule;
return bb._pending_block_header_state.prev_pending_schedule.schedule;
}

optional<producer_schedule_type> controller::proposed_producers()const {
Expand Down
9 changes: 4 additions & 5 deletions libraries/chain/fork_database.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,17 @@ namespace eosio { namespace chain {
ordered_non_unique< tag<by_prev>, const_mem_fun<block_header_state, const block_id_type&, &block_header_state::prev> >,
ordered_non_unique< tag<by_block_num>,
composite_key< block_state,
member<block_header_state,uint32_t,&block_header_state::block_num>,
member<detail::block_header_state_common,uint32_t,&detail::block_header_state_common::block_num>,
member<block_state,bool,&block_state::in_current_chain>
>,
composite_key_compare< std::less<uint32_t>, std::greater<bool> >
>,
ordered_non_unique< tag<by_lib_block_num>,
composite_key< block_header_state,
member<block_header_state,uint32_t,&block_header_state::dpos_irreversible_blocknum>,
member<block_header_state,uint32_t,&block_header_state::bft_irreversible_blocknum>,
member<block_header_state,uint32_t,&block_header_state::block_num>
member<detail::block_header_state_common,uint32_t,&detail::block_header_state_common::dpos_irreversible_blocknum>,
member<detail::block_header_state_common,uint32_t,&detail::block_header_state_common::block_num>
>,
composite_key_compare< std::greater<uint32_t>, std::greater<uint32_t>, std::greater<uint32_t> >
composite_key_compare< std::greater<uint32_t>, std::greater<uint32_t> >
>
>
> fork_multi_index_type;
Expand Down
116 changes: 68 additions & 48 deletions libraries/chain/include/eosio/chain/block_header_state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,34 @@ namespace eosio { namespace chain {

struct block_header_state;

struct pending_block_header_state {
uint32_t block_num = 0;
namespace detail {
struct block_header_state_common {
uint32_t block_num = 0;
uint32_t dpos_proposed_irreversible_blocknum = 0;
uint32_t dpos_irreversible_blocknum = 0;
producer_schedule_type active_schedule;
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;
public_key_type block_signing_key;
vector<uint8_t> confirm_count;
};

struct schedule_info {
uint32_t schedule_lib_num = 0; /// last irr block num
digest_type schedule_hash;
producer_schedule_type schedule;
};
}

struct pending_block_header_state : public detail::block_header_state_common {
detail::schedule_info prev_pending_schedule;
bool was_pending_promoted = false;
block_id_type previous;
block_timestamp_type timestamp;
account_name producer;
uint16_t confirmed = 1;
uint32_t dpos_proposed_irreversible_blocknum = 0;
uint32_t dpos_irreversible_blocknum = 0;
block_timestamp_type timestamp;
uint32_t active_schedule_version = 0;
uint32_t prev_pending_schedule_lib_num = 0; /// last irr block num
digest_type prev_pending_schedule_hash;
producer_schedule_type prev_pending_schedule;
producer_schedule_type active_schedule;
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;
public_key_type block_signing_key;
vector<uint8_t> confirm_count;
bool was_pending_promoted = false;
uint16_t confirmed = 1;

signed_block_header make_block_header( const checksum256_type& transaction_mroot,
const checksum256_type& action_mroot,
Expand All @@ -36,7 +45,7 @@ struct pending_block_header_state {
block_header_state finish_next( signed_block_header& h,
const std::function<signature_type(const digest_type&)>& signer )&&;

private:
protected:
block_header_state _finish_next( const signed_block_header& h )&&;
};

Expand All @@ -45,46 +54,57 @@ struct pending_block_header_state {
* @struct block_header_state
* @brief defines the minimum state necessary to validate transaction headers
*/
struct block_header_state {
block_id_type id;
uint32_t block_num = 0;
signed_block_header header;
uint32_t dpos_proposed_irreversible_blocknum = 0;
uint32_t dpos_irreversible_blocknum = 0;
uint32_t bft_irreversible_blocknum = 0;
uint32_t pending_schedule_lib_num = 0; /// last irr block num
digest_type pending_schedule_hash;
producer_schedule_type pending_schedule;
producer_schedule_type active_schedule;
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;
public_key_type block_signing_key;
vector<uint8_t> confirm_count;
struct block_header_state : public detail::block_header_state_common {
block_id_type id;
signed_block_header header;
detail::schedule_info pending_schedule;

block_header_state() = default;

block_header_state( detail::block_header_state_common&& base )
:detail::block_header_state_common( std::move(base) )
{}

pending_block_header_state next( block_timestamp_type when, uint16_t num_prev_blocks_to_confirm )const;

block_header_state next( const signed_block_header& h, bool skip_validate_signee = false )const;

bool has_pending_producers()const { return pending_schedule.producers.size(); }
uint32_t calc_dpos_last_irreversible( account_name producer_of_next_block )const;
bool is_active_producer( account_name n )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;
bool is_active_producer( account_name n )const;

producer_key get_scheduled_producer( block_timestamp_type t )const;
const block_id_type& prev()const { return header.previous; }
digest_type sig_digest()const;
void sign( const std::function<signature_type(const digest_type&)>& signer );
public_key_type signee()const;
void verify_signee(const public_key_type& signee)const;
producer_key get_scheduled_producer( block_timestamp_type t )const;
const block_id_type& prev()const { return header.previous; }
digest_type sig_digest()const;
void sign( const std::function<signature_type(const digest_type&)>& signer );
public_key_type signee()const;
void verify_signee(const public_key_type& signee)const;
};



} } /// namespace eosio::chain

FC_REFLECT( eosio::chain::block_header_state,
(id)(block_num)(header)(dpos_proposed_irreversible_blocknum)(dpos_irreversible_blocknum)(bft_irreversible_blocknum)
(pending_schedule_lib_num)(pending_schedule_hash)
(pending_schedule)(active_schedule)(blockroot_merkle)
(producer_to_last_produced)(producer_to_last_implied_irb)(block_signing_key)
(confirm_count) )
FC_REFLECT( eosio::chain::detail::block_header_state_common,
(block_num)
(dpos_proposed_irreversible_blocknum)
(dpos_irreversible_blocknum)
(active_schedule)
(blockroot_merkle)
(producer_to_last_produced)
(producer_to_last_implied_irb)
(block_signing_key)
(confirm_count)
)

FC_REFLECT( eosio::chain::detail::schedule_info,
(schedule_lib_num)
(schedule_hash)
(schedule)
)

FC_REFLECT_DERIVED( eosio::chain::block_header_state, (eosio::chain::detail::block_header_state_common),
(id)
(header)
(pending_schedule)
)
6 changes: 3 additions & 3 deletions unittests/block_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@ BOOST_AUTO_TEST_CASE(block_with_invalid_tx_test)
// Re-sign the transaction
signed_tx.signatures.clear();
signed_tx.sign(main.get_private_key(config::system_account_name, "active"), main.control->get_chain_id());
// Replace the valid transaction with the invalid transaction
// Replace the valid transaction with the invalid transaction
auto invalid_packed_tx = packed_transaction(signed_tx);
copy_b->transactions.back().trx = invalid_packed_tx;

// Re-sign the block
auto header_bmroot = digest_type::hash( std::make_pair( copy_b->digest(), main.control->head_block_state()->blockroot_merkle.get_root() ) );
auto sig_digest = digest_type::hash( std::make_pair(header_bmroot, main.control->head_block_state()->pending_schedule_hash) );
auto sig_digest = digest_type::hash( std::make_pair(header_bmroot, main.control->head_block_state()->pending_schedule.schedule_hash) );
copy_b->producer_signature = main.get_private_key(config::system_account_name, "active").sign(sig_digest);

// Push block with invalid transaction to other chain
Expand Down Expand Up @@ -78,7 +78,7 @@ std::pair<signed_block_ptr, signed_block_ptr> corrupt_trx_in_block(validating_te

// Re-sign the block
auto header_bmroot = digest_type::hash( std::make_pair( copy_b->digest(), main.control->head_block_state()->blockroot_merkle.get_root() ) );
auto sig_digest = digest_type::hash( std::make_pair(header_bmroot, main.control->head_block_state()->pending_schedule_hash) );
auto sig_digest = digest_type::hash( std::make_pair(header_bmroot, main.control->head_block_state()->pending_schedule.schedule_hash) );
copy_b->producer_signature = main.get_private_key(b->producer, "active").sign(sig_digest);
return std::pair<signed_block_ptr, signed_block_ptr>(b, copy_b);
}
Expand Down
2 changes: 1 addition & 1 deletion unittests/forked_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ BOOST_AUTO_TEST_CASE( fork_with_bad_block ) try {

// re-sign the block
auto header_bmroot = digest_type::hash( std::make_pair( copy_b->digest(), fork.block_merkle.get_root() ) );
auto sig_digest = digest_type::hash( std::make_pair(header_bmroot, remote.control->head_block_state()->pending_schedule_hash) );
auto sig_digest = digest_type::hash( std::make_pair(header_bmroot, remote.control->head_block_state()->pending_schedule.schedule_hash) );
copy_b->producer_signature = remote.get_private_key(N(b), "active").sign(sig_digest);

// add this new block to our corrupted block merkle
Expand Down

0 comments on commit be795a8

Please sign in to comment.