Polish out-of-order-block handling, write test case
This commit is contained in:
parent
9c0c588ed6
commit
eeeab17477
3 changed files with 61 additions and 6 deletions
|
|
@ -51,7 +51,7 @@ shared_ptr<fork_item> fork_database::push_block(const signed_block& b)
|
||||||
auto item = std::make_shared<fork_item>(b);
|
auto item = std::make_shared<fork_item>(b);
|
||||||
try {
|
try {
|
||||||
_push_block(item);
|
_push_block(item);
|
||||||
}
|
}
|
||||||
catch ( const unlinkable_block_exception& e )
|
catch ( const unlinkable_block_exception& e )
|
||||||
{
|
{
|
||||||
wlog( "Pushing block to fork database that failed to link." );
|
wlog( "Pushing block to fork database that failed to link." );
|
||||||
|
|
@ -65,13 +65,14 @@ void fork_database::_push_block(const item_ptr& item)
|
||||||
if( _head ) // make sure the block is within the range that we are caching
|
if( _head ) // make sure the block is within the range that we are caching
|
||||||
{
|
{
|
||||||
FC_ASSERT( item->num > std::max<int64_t>( 0, int64_t(_head->num) - (_max_size) ) );
|
FC_ASSERT( item->num > std::max<int64_t>( 0, int64_t(_head->num) - (_max_size) ) );
|
||||||
FC_ASSERT( item->num < _head->num + 32 );
|
FC_ASSERT( item->num < _head->num + MAX_BLOCK_REORDERING );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( _head && item->previous_id() != block_id_type() )
|
if( _head && item->previous_id() != block_id_type() )
|
||||||
{
|
{
|
||||||
auto itr = _index.get<block_id>().find(item->previous_id());
|
auto& index = _index.get<block_id>();
|
||||||
GRAPHENE_ASSERT(itr != _index.get<block_id>().end(), unlinkable_block_exception, "block does not link to known chain");
|
auto itr = index.find(item->previous_id());
|
||||||
|
GRAPHENE_ASSERT(itr != index.end(), unlinkable_block_exception, "block does not link to known chain");
|
||||||
FC_ASSERT(!(*itr)->invalid);
|
FC_ASSERT(!(*itr)->invalid);
|
||||||
item->prev = *itr;
|
item->prev = *itr;
|
||||||
}
|
}
|
||||||
|
|
@ -97,14 +98,13 @@ void fork_database::_push_block(const item_ptr& item)
|
||||||
void fork_database::_push_next( const item_ptr& new_item )
|
void fork_database::_push_next( const item_ptr& new_item )
|
||||||
{
|
{
|
||||||
auto& prev_idx = _unlinked_index.get<by_previous>();
|
auto& prev_idx = _unlinked_index.get<by_previous>();
|
||||||
vector<item_ptr> newly_inserted;
|
|
||||||
|
|
||||||
auto itr = prev_idx.find( new_item->id );
|
auto itr = prev_idx.find( new_item->id );
|
||||||
while( itr != prev_idx.end() )
|
while( itr != prev_idx.end() )
|
||||||
{
|
{
|
||||||
auto tmp = *itr;
|
auto tmp = *itr;
|
||||||
prev_idx.erase( itr );
|
prev_idx.erase( itr );
|
||||||
_push_block( tmp );
|
_push_block( tmp );
|
||||||
|
|
||||||
itr = prev_idx.find( new_item->id );
|
itr = prev_idx.find( new_item->id );
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,8 @@ namespace graphene { namespace chain {
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef vector<item_ptr> branch_type;
|
typedef vector<item_ptr> branch_type;
|
||||||
|
/// The maximum number of blocks that may be skipped in an out-of-order push
|
||||||
|
const static int MAX_BLOCK_REORDERING = 32;
|
||||||
|
|
||||||
fork_database();
|
fork_database();
|
||||||
void reset();
|
void reset();
|
||||||
|
|
|
||||||
|
|
@ -276,6 +276,59 @@ BOOST_AUTO_TEST_CASE( fork_blocks )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE( out_of_order_blocks )
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
fc::temp_directory data_dir1( graphene::utilities::temp_directory_path() );
|
||||||
|
fc::temp_directory data_dir2( graphene::utilities::temp_directory_path() );
|
||||||
|
|
||||||
|
database db1;
|
||||||
|
db1.open(data_dir1.path(), make_genesis);
|
||||||
|
database db2;
|
||||||
|
db2.open(data_dir2.path(), make_genesis);
|
||||||
|
BOOST_CHECK( db1.get_chain_id() == db2.get_chain_id() );
|
||||||
|
|
||||||
|
auto init_account_priv_key = fc::ecc::private_key::regenerate(fc::sha256::hash(string("null_key")) );
|
||||||
|
auto b1 = db1.generate_block(db1.get_slot_time(1), db1.get_scheduled_witness(1).first, init_account_priv_key, database::skip_nothing);
|
||||||
|
auto b2 = db1.generate_block(db1.get_slot_time(1), db1.get_scheduled_witness(1).first, init_account_priv_key, database::skip_nothing);
|
||||||
|
auto b3 = db1.generate_block(db1.get_slot_time(1), db1.get_scheduled_witness(1).first, init_account_priv_key, database::skip_nothing);
|
||||||
|
auto b4 = db1.generate_block(db1.get_slot_time(1), db1.get_scheduled_witness(1).first, init_account_priv_key, database::skip_nothing);
|
||||||
|
auto b5 = db1.generate_block(db1.get_slot_time(1), db1.get_scheduled_witness(1).first, init_account_priv_key, database::skip_nothing);
|
||||||
|
auto b6 = db1.generate_block(db1.get_slot_time(1), db1.get_scheduled_witness(1).first, init_account_priv_key, database::skip_nothing);
|
||||||
|
auto b7 = db1.generate_block(db1.get_slot_time(1), db1.get_scheduled_witness(1).first, init_account_priv_key, database::skip_nothing);
|
||||||
|
auto b8 = db1.generate_block(db1.get_slot_time(1), db1.get_scheduled_witness(1).first, init_account_priv_key, database::skip_nothing);
|
||||||
|
auto b9 = db1.generate_block(db1.get_slot_time(1), db1.get_scheduled_witness(1).first, init_account_priv_key, database::skip_nothing);
|
||||||
|
auto b10 = db1.generate_block(db1.get_slot_time(1), db1.get_scheduled_witness(1).first, init_account_priv_key, database::skip_nothing);
|
||||||
|
auto b11 = db1.generate_block(db1.get_slot_time(1), db1.get_scheduled_witness(1).first, init_account_priv_key, database::skip_nothing);
|
||||||
|
auto b12 = db1.generate_block(db1.get_slot_time(1), db1.get_scheduled_witness(1).first, init_account_priv_key, database::skip_nothing);
|
||||||
|
BOOST_CHECK_EQUAL(db1.head_block_num(), 12);
|
||||||
|
BOOST_CHECK_EQUAL(db2.head_block_num(), 0);
|
||||||
|
PUSH_BLOCK( db2, b1 );
|
||||||
|
BOOST_CHECK_EQUAL(db2.head_block_num(), 1);
|
||||||
|
PUSH_BLOCK( db2, b3 );
|
||||||
|
BOOST_CHECK_EQUAL(db2.head_block_num(), 1);
|
||||||
|
PUSH_BLOCK( db2, b2 );
|
||||||
|
BOOST_CHECK_EQUAL(db2.head_block_num(), 3);
|
||||||
|
PUSH_BLOCK( db2, b5 );
|
||||||
|
PUSH_BLOCK( db2, b6 );
|
||||||
|
PUSH_BLOCK( db2, b7 );
|
||||||
|
BOOST_CHECK_EQUAL(db2.head_block_num(), 3);
|
||||||
|
PUSH_BLOCK( db2, b4 );
|
||||||
|
BOOST_CHECK_EQUAL(db2.head_block_num(), 7);
|
||||||
|
PUSH_BLOCK( db2, b8 );
|
||||||
|
BOOST_CHECK_EQUAL(db2.head_block_num(), 8);
|
||||||
|
PUSH_BLOCK( db2, b11 );
|
||||||
|
PUSH_BLOCK( db2, b10 );
|
||||||
|
PUSH_BLOCK( db2, b12 );
|
||||||
|
BOOST_CHECK_EQUAL(db2.head_block_num(), 8);
|
||||||
|
PUSH_BLOCK( db2, b9 );
|
||||||
|
BOOST_CHECK_EQUAL(db2.head_block_num(), 12);
|
||||||
|
} catch (fc::exception& e) {
|
||||||
|
edump((e.to_detail_string()));
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE( undo_pending )
|
BOOST_AUTO_TEST_CASE( undo_pending )
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue