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

Issue3088 - BFT Double Confirmation Requirment #3092

Merged
merged 3 commits into from
May 15, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
62 changes: 45 additions & 17 deletions libraries/chain/block_header_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,18 @@ namespace eosio { namespace chain {
return active_schedule.producers[index];
}

uint32_t block_header_state::calc_dpos_last_irreversible()const {
vector<uint32_t> blocknums; blocknums.reserve( producer_to_last_implied_irb.size() );
for( auto& i : producer_to_last_implied_irb ) {
blocknums.push_back(i.second);
}
/// 2/3 must be greater, so if I go 1/3 into the list sorted from low to high, then 2/3 are greater

if( blocknums.size() == 0 ) return 0;
/// TODO: update to nth_element
std::sort( blocknums.begin(), blocknums.end() );
return blocknums[ (blocknums.size()-1) / 3 ];
}

/**
* Generate a template block header state for a given block time, it will not
Expand All @@ -29,28 +41,32 @@ namespace eosio { namespace chain {
} else {
(when = header.timestamp).slot++;
}
result.header.timestamp = when;
result.header.previous = id;
result.header.schedule_version = active_schedule.version;

auto prokey = get_scheduled_producer(when);
result.block_signing_key = prokey.block_signing_key;
result.header.producer = prokey.producer_name;

result.pending_schedule_lib_num = pending_schedule_lib_num;
result.pending_schedule_hash = pending_schedule_hash;
result.block_num = block_num + 1;
result.producer_to_last_produced = producer_to_last_produced;
result.header.timestamp = when;
result.header.previous = id;
result.header.schedule_version = active_schedule.version;

auto prokey = get_scheduled_producer(when);
result.block_signing_key = prokey.block_signing_key;
result.header.producer = prokey.producer_name;

result.pending_schedule_lib_num = pending_schedule_lib_num;
result.pending_schedule_hash = pending_schedule_hash;
result.block_num = block_num + 1;
result.producer_to_last_produced = producer_to_last_produced;
result.producer_to_last_implied_irb = producer_to_last_implied_irb;
result.producer_to_last_produced[prokey.producer_name] = result.block_num;
result.blockroot_merkle = blockroot_merkle;
result.blockroot_merkle.append( id );

auto block_mroot = result.blockroot_merkle.get_root();

result.active_schedule = active_schedule;
result.pending_schedule = pending_schedule;
result.dpos_irreversible_blocknum = dpos_irreversible_blocknum;
result.bft_irreversible_blocknum = bft_irreversible_blocknum;
result.active_schedule = active_schedule;
result.pending_schedule = pending_schedule;
result.dpos_proposed_irreversible_blocknum = dpos_proposed_irreversible_blocknum;
result.bft_irreversible_blocknum = bft_irreversible_blocknum;

result.producer_to_last_implied_irb[prokey.producer_name] = result.dpos_proposed_irreversible_blocknum;
result.dpos_irreversible_blocknum = result.calc_dpos_last_irreversible();

/// grow the confirmed count
static_assert(std::numeric_limits<uint8_t>::max() >= (config::max_producers * 2 / 3) + 1, "8bit confirmations may not be able to hold all of the needed confirmations");
Expand Down Expand Up @@ -88,7 +104,19 @@ namespace eosio { namespace chain {
new_producer_to_last_produced[pro.producer_name] = dpos_irreversible_blocknum;
}
}

flat_map<account_name,uint32_t> new_producer_to_last_implied_irb;
for( const auto& pro : active_schedule.producers ) {
auto existing = producer_to_last_implied_irb.find( pro.producer_name );
if( existing != producer_to_last_implied_irb.end() ) {
new_producer_to_last_implied_irb[pro.producer_name] = existing->second;
} else {
new_producer_to_last_implied_irb[pro.producer_name] = dpos_irreversible_blocknum;
}
}

producer_to_last_produced = move( new_producer_to_last_produced );
producer_to_last_implied_irb = move( new_producer_to_last_implied_irb);
producer_to_last_produced[header.producer] = block_num;

return true;
Expand Down Expand Up @@ -175,7 +203,7 @@ namespace eosio { namespace chain {
if( confirm_count[i] == 0 )
{
uint32_t block_num_for_i = block_num - (uint32_t)(confirm_count.size() - 1 - i);
dpos_irreversible_blocknum = block_num_for_i;
dpos_proposed_irreversible_blocknum = block_num_for_i;
//idump((dpos2_lib)(block_num)(dpos_irreversible_blocknum));

if (i == confirm_count.size() - 1) {
Expand Down
8 changes: 5 additions & 3 deletions libraries/chain/include/eosio/chain/block_header_state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ 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
Expand All @@ -20,6 +21,7 @@ struct block_header_state {
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;
vector<header_confirmation> confirmations;
Expand All @@ -34,7 +36,7 @@ struct block_header_state {


bool has_pending_producers()const { return pending_schedule.producers.size(); }
//uint32_t calc_dpos_last_irreversible()const;
uint32_t calc_dpos_last_irreversible()const;
bool is_active_producer( account_name n )const;

/*
Expand All @@ -56,8 +58,8 @@ struct block_header_state {
} } /// namespace eosio::chain

FC_REFLECT( eosio::chain::block_header_state,
(id)(block_num)(header)(dpos_irreversible_blocknum)(bft_irreversible_blocknum)
(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)(block_signing_key)
(producer_to_last_produced)(producer_to_last_implied_irb)(block_signing_key)
(confirm_count)(confirmations) )
4 changes: 2 additions & 2 deletions unittests/database_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ BOOST_AUTO_TEST_SUITE(database_tests)
};

// Check the last irreversible block number is set correctly
const auto expected_last_irreversible_block_number = calc_exp_last_irr_block_num(num_of_blocks_to_prod) + 1;
const auto expected_last_irreversible_block_number = calc_exp_last_irr_block_num(num_of_blocks_to_prod);
BOOST_TEST(test.control->head_block_state()->dpos_irreversible_blocknum == expected_last_irreversible_block_number);
// Check that block 201 cannot be found (only 20 blocks exist)
BOOST_TEST(test.control->fetch_block_by_number(num_of_blocks_to_prod + 1 + 1) == nullptr);
Expand All @@ -87,7 +87,7 @@ BOOST_AUTO_TEST_SUITE(database_tests)
test.produce_blocks(next_num_of_blocks_to_prod);

const auto next_expected_last_irreversible_block_number = calc_exp_last_irr_block_num(
num_of_blocks_to_prod + next_num_of_blocks_to_prod) + 1;
num_of_blocks_to_prod + next_num_of_blocks_to_prod);
// Check the last irreversible block number is updated correctly
BOOST_TEST(test.control->head_block_state()->dpos_irreversible_blocknum == next_expected_last_irreversible_block_number);
// Check that block 201 can now be found
Expand Down
12 changes: 7 additions & 5 deletions unittests/producer_schedule_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ BOOST_FIXTURE_TEST_CASE( producer_schedule_promotion_test, TESTER ) try {
BOOST_CHECK_EQUAL( control->pending_producers().version, 1 );
BOOST_CHECK_EQUAL( true, compare_schedules( sch1, control->pending_producers() ) );
BOOST_CHECK_EQUAL( control->active_producers().version, 0 );
produce_block();
produce_block(); // Starts new block which promotes the pending schedule to active
BOOST_CHECK_EQUAL( control->active_producers().version, 1 );
BOOST_CHECK_EQUAL( true, compare_schedules( sch1, control->active_producers() ) );
Expand All @@ -234,18 +235,19 @@ BOOST_FIXTURE_TEST_CASE( producer_schedule_promotion_test, TESTER ) try {
BOOST_REQUIRE_EQUAL( true, control->proposed_producers().valid() );
BOOST_CHECK_EQUAL( true, compare_schedules( sch2, *control->proposed_producers() ) );

produce_block(); // Alice produces the last block of her first round.
produce_block();
produce_blocks(23); // Alice produces the last block of her first round.
// Bob's first block (which advances LIB to Alice's last block) is started but not finalized.
BOOST_REQUIRE_EQUAL( control->head_block_producer(), N(alice) );
BOOST_REQUIRE_EQUAL( control->pending_block_state()->header.producer, N(bob) );
BOOST_CHECK_EQUAL( control->pending_producers().version, 2 );

produce_blocks(11); // Bob produces his first 11 blocks
produce_blocks(12); // Bob produces his first 11 blocks
BOOST_CHECK_EQUAL( control->active_producers().version, 1 );
produce_block(); // Bob produces his 12th block.
produce_blocks(12); // Bob produces his 12th block.
// Alice's first block of the second round is started but not finalized (which advances LIB to Bob's last block).
BOOST_REQUIRE_EQUAL( control->head_block_producer(), N(bob) );
BOOST_REQUIRE_EQUAL( control->pending_block_state()->header.producer, N(alice) );
BOOST_REQUIRE_EQUAL( control->head_block_producer(), N(alice) );
BOOST_REQUIRE_EQUAL( control->pending_block_state()->header.producer, N(bob) );
BOOST_CHECK_EQUAL( control->active_producers().version, 2 );
BOOST_CHECK_EQUAL( true, compare_schedules( sch2, control->active_producers() ) );

Expand Down