Merge pull request #104 from peerplays-network/feature/GRPH-76

Short-cut long sequences of missed blocks
This commit is contained in:
Bobinson K B 2019-09-07 00:51:12 +05:30 committed by GitHub
commit db8efafc62
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 61 additions and 37 deletions

View file

@ -612,7 +612,8 @@ void database::_apply_block( const signed_block& next_block )
if (global_props.parameters.witness_schedule_algorithm == GRAPHENE_WITNESS_SCHEDULED_ALGORITHM)
update_witness_schedule(next_block);
update_global_dynamic_data(next_block);
const uint32_t missed = update_witness_missed_blocks( next_block );
update_global_dynamic_data( next_block, missed );
update_signing_witness(signing_witness, next_block);
update_last_irreversible_block();

View file

@ -43,43 +43,13 @@
namespace graphene { namespace chain {
void database::update_global_dynamic_data( const signed_block& b )
void database::update_global_dynamic_data( const signed_block& b, const uint32_t missed_blocks )
{
const dynamic_global_property_object& _dgp = dynamic_global_property_id_type(0)(*this);
const global_property_object& gpo = get_global_properties();
uint32_t missed_blocks = get_slot_at_time( b.timestamp );
//#define DIRTY_TRICK // problem with missed_blocks can occur when "maintenance_interval" set to few minutes
#ifdef DIRTY_TRICK
if (missed_blocks != 0) {
#else
assert( missed_blocks != 0 );
#endif
// bad if-condition, this code needs to execute for both shuffled and rng algorithms
// if (gpo.parameters.witness_schedule_algorithm == GRAPHENE_WITNESS_SHUFFLED_ALGORITHM)
// {
missed_blocks--;
for( uint32_t i = 0; i < missed_blocks; ++i ) {
const auto& witness_missed = get_scheduled_witness( i+1 )(*this);
if( witness_missed.id != b.witness ) {
/*
const auto& witness_account = witness_missed.witness_account(*this);
if( (fc::time_point::now() - b.timestamp) < fc::seconds(30) )
wlog( "Witness ${name} missed block ${n} around ${t}", ("name",witness_account.name)("n",b.block_num())("t",b.timestamp) );
*/
modify( witness_missed, [&]( witness_object& w ) {
w.total_missed++;
});
}
}
// }
#ifdef DIRTY_TRICK
}
#endif
// dynamic global properties updating
modify( _dgp, [&]( dynamic_global_property_object& dgp ){
modify( _dgp, [&b,this,missed_blocks]( dynamic_global_property_object& dgp ){
secret_hash_type::encoder enc;
fc::raw::pack( enc, dgp.random );
fc::raw::pack( enc, b.previous_secret );
@ -87,9 +57,10 @@ void database::update_global_dynamic_data( const signed_block& b )
_random_number_generator = fc::hash_ctr_rng<secret_hash_type, 20>(dgp.random.data());
if( BOOST_UNLIKELY( b.block_num() == 1 ) )
const uint32_t block_num = b.block_num();
if( BOOST_UNLIKELY( block_num == 1 ) )
dgp.recently_missed_count = 0;
else if( _checkpoints.size() && _checkpoints.rbegin()->first >= b.block_num() )
else if( _checkpoints.size() && _checkpoints.rbegin()->first >= block_num )
dgp.recently_missed_count = 0;
else if( missed_blocks )
dgp.recently_missed_count += GRAPHENE_RECENTLY_MISSED_COUNT_INCREMENT*missed_blocks;
@ -98,7 +69,7 @@ void database::update_global_dynamic_data( const signed_block& b )
else if( dgp.recently_missed_count > 0 )
dgp.recently_missed_count--;
dgp.head_block_number = b.block_num();
dgp.head_block_number = block_num;
dgp.head_block_id = b.id();
dgp.time = b.timestamp;
dgp.current_witness = b.witness;

View file

@ -226,6 +226,22 @@ void database::update_witness_schedule(const signed_block& next_block)
idump( ( double(total_time/1000000.0)/calls) );
}
uint32_t database::update_witness_missed_blocks( const signed_block& b )
{
uint32_t missed_blocks = get_slot_at_time( b.timestamp );
FC_ASSERT( missed_blocks != 0, "Trying to push double-produced block onto current block?!" );
missed_blocks--;
const auto& witnesses = witness_schedule_id_type()(*this).current_shuffled_witnesses;
if( missed_blocks < witnesses.size() )
for( uint32_t i = 0; i < missed_blocks; ++i ) {
const auto& witness_missed = get_scheduled_witness( i+1 )(*this);
modify( witness_missed, []( witness_object& w ) {
w.total_missed++;
});
}
return missed_blocks;
}
uint32_t database::witness_participation_rate()const
{
const global_property_object& gpo = get_global_properties();

View file

@ -488,8 +488,11 @@ namespace graphene { namespace chain {
const witness_object& _validate_block_header( const signed_block& next_block )const;
void create_block_summary(const signed_block& next_block);
//////////////////// db_witness_schedule.cpp ////////////////////
uint32_t update_witness_missed_blocks( const signed_block& b );
//////////////////// db_update.cpp ////////////////////
void update_global_dynamic_data( const signed_block& b );
void update_global_dynamic_data( const signed_block& b, const uint32_t missed_blocks );
void update_signing_witness(const witness_object& signing_witness, const signed_block& new_block);
void update_last_irreversible_block();
void clear_expired_transactions();

View file

@ -33,6 +33,7 @@
#include <graphene/chain/proposal_object.hpp>
#include <graphene/chain/market_object.hpp>
#include <graphene/chain/witness_schedule_object.hpp>
#include <graphene/chain/witness_object.hpp>
#include <graphene/utilities/tempdir.hpp>
@ -1288,18 +1289,50 @@ BOOST_AUTO_TEST_CASE( genesis_reserve_ids )
}
}
BOOST_FIXTURE_TEST_CASE( miss_some_blocks, database_fixture )
{ try {
std::vector<witness_id_type> witnesses = witness_schedule_id_type()(db).current_shuffled_witnesses;
BOOST_CHECK_EQUAL( 10, witnesses.size() );
// database_fixture constructor calls generate_block once, signed by witnesses[0]
generate_block(); // witnesses[1]
generate_block(); // witnesses[2]
for( const auto& id : witnesses )
BOOST_CHECK_EQUAL( 0, id(db).total_missed );
// generate_blocks generates another block *now* (witnesses[3])
// and one at now+10 blocks (witnesses[12%10])
generate_blocks( db.head_block_time() + db.get_global_properties().parameters.block_interval * 10, true );
// i. e. 8 blocks are missed in between by witness[4..11%10]
for( uint32_t i = 0; i < witnesses.size(); i++ )
BOOST_CHECK_EQUAL( (i+7) % 10 < 2 ? 0 : 1, witnesses[i](db).total_missed );
} FC_LOG_AND_RETHROW() }
BOOST_FIXTURE_TEST_CASE( miss_many_blocks, database_fixture )
{
try
{
auto get_misses = []( database& db ) {
std::map< witness_id_type, uint32_t > misses;
for( const auto& witness_id : witness_schedule_id_type()(db).current_shuffled_witnesses )
misses[witness_id] = witness_id(db).total_missed;
return misses;
};
generate_block();
generate_block();
generate_block();
auto missed_before = get_misses( db );
// miss 10 maintenance intervals
generate_blocks( db.get_dynamic_global_properties().next_maintenance_time + db.get_global_properties().parameters.maintenance_interval * 10, true );
generate_block();
generate_block();
generate_block();
auto missed_after = get_misses( db );
BOOST_CHECK_EQUAL( missed_before.size(), missed_after.size() );
for( const auto& miss : missed_before )
{
const auto& after = missed_after.find( miss.first );
BOOST_REQUIRE( after != missed_after.end() );
BOOST_CHECK_EQUAL( miss.second, after->second );
}
}
catch (fc::exception& e)
{