Merge branch 'remove_leveldb'
This commit is contained in:
commit
4aa1d6b339
7 changed files with 139 additions and 34 deletions
|
|
@ -53,6 +53,7 @@ namespace graphene { namespace chain {
|
|||
checksum_type signed_block::calculate_merkle_root()const
|
||||
{
|
||||
if( transactions.size() == 0 ) return checksum_type();
|
||||
wdump((transactions.size()));
|
||||
|
||||
vector<digest_type> ids;
|
||||
ids.resize( ((transactions.size() + 1)/2)*2 );
|
||||
|
|
|
|||
|
|
@ -8,12 +8,29 @@ struct index_entry
|
|||
uint32_t block_size = 0;
|
||||
block_id_type block_id;
|
||||
};
|
||||
}}
|
||||
FC_REFLECT( graphene::chain::index_entry, (block_pos)(block_size)(block_id) );
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
void block_database::open( const fc::path& dbdir )
|
||||
{
|
||||
_block_num_to_pos.open( (dbdir/"index").generic_string().c_str(), std::fstream::binary );
|
||||
_blocks.open( (dbdir/"blocks").generic_string().c_str(), std::fstream::binary );
|
||||
}
|
||||
{ try {
|
||||
idump((sizeof(index_entry)) );
|
||||
fc::create_directories(dbdir);
|
||||
_block_num_to_pos.exceptions(std::ios_base::failbit | std::ios_base::badbit);
|
||||
_blocks.exceptions(std::ios_base::failbit | std::ios_base::badbit);
|
||||
|
||||
if( !fc::exists( dbdir/"index" ) )
|
||||
{
|
||||
_block_num_to_pos.open( (dbdir/"index").generic_string().c_str(), std::fstream::binary | std::fstream::in | std::fstream::out | std::fstream::trunc);
|
||||
_blocks.open( (dbdir/"blocks").generic_string().c_str(), std::fstream::binary | std::fstream::in | std::fstream::out | std::fstream::trunc);
|
||||
}
|
||||
else
|
||||
{
|
||||
_block_num_to_pos.open( (dbdir/"index").generic_string().c_str(), std::fstream::binary | std::fstream::in | std::fstream::out );
|
||||
_blocks.open( (dbdir/"blocks").generic_string().c_str(), std::fstream::binary | std::fstream::in | std::fstream::out );
|
||||
}
|
||||
} FC_CAPTURE_AND_RETHROW( (dbdir) ) }
|
||||
|
||||
|
||||
bool block_database::is_open()const
|
||||
|
|
@ -51,7 +68,7 @@ void block_database::store( const block_id_type& id, const signed_block& b )
|
|||
|
||||
|
||||
void block_database::remove( const block_id_type& id )
|
||||
{
|
||||
{ try {
|
||||
index_entry e;
|
||||
auto index_pos = sizeof(e)*block_header::num_from_id(id);
|
||||
_block_num_to_pos.seekg( 0, _block_num_to_pos.end );
|
||||
|
|
@ -60,12 +77,13 @@ void block_database::remove( const block_id_type& id )
|
|||
_block_num_to_pos.seekg( index_pos );
|
||||
_block_num_to_pos.read( (char*)&e, sizeof(e) );
|
||||
|
||||
FC_ASSERT( e.block_id == id );
|
||||
|
||||
e.block_size = 0;
|
||||
_block_num_to_pos.seekp( sizeof(e)*block_header::num_from_id(id) );
|
||||
_block_num_to_pos.write( (char*)&e, sizeof(e) );
|
||||
}
|
||||
if( e.block_id == id )
|
||||
{
|
||||
e.block_size = 0;
|
||||
_block_num_to_pos.seekp( sizeof(e)*block_header::num_from_id(id) );
|
||||
_block_num_to_pos.write( (char*)&e, sizeof(e) );
|
||||
}
|
||||
} FC_CAPTURE_AND_RETHROW( (id) ) }
|
||||
|
||||
|
||||
|
||||
|
|
@ -100,7 +118,7 @@ block_id_type block_database::fetch_block_id( uint32_t block_num )const
|
|||
|
||||
|
||||
optional<signed_block> block_database::fetch_optional( const block_id_type& id )const
|
||||
{
|
||||
{ try {
|
||||
index_entry e;
|
||||
auto index_pos = sizeof(e)*block_header::num_from_id(id);
|
||||
_block_num_to_pos.seekg( 0, _block_num_to_pos.end );
|
||||
|
|
@ -114,25 +132,31 @@ optional<signed_block> block_database::fetch_optional( const block_id_type& id )
|
|||
vector<char> data( e.block_size );
|
||||
_blocks.seekg( e.block_pos );
|
||||
_blocks.read( data.data(), e.block_size );
|
||||
return fc::raw::unpack<signed_block>(data);
|
||||
}
|
||||
auto result = fc::raw::unpack<signed_block>(data);
|
||||
FC_ASSERT( result.id() == e.block_id );
|
||||
return result;
|
||||
} FC_CAPTURE_AND_RETHROW( (id) ) }
|
||||
|
||||
|
||||
optional<signed_block> block_database::fetch_by_number( uint32_t block_num )const
|
||||
{
|
||||
{ try {
|
||||
index_entry e;
|
||||
auto index_pos = sizeof(e)*block_num;
|
||||
_block_num_to_pos.seekg( 0, _block_num_to_pos.end );
|
||||
FC_ASSERT( _block_num_to_pos.tellg() > index_pos );
|
||||
|
||||
_block_num_to_pos.seekg( index_pos );
|
||||
_block_num_to_pos.seekg( index_pos, _block_num_to_pos.beg );
|
||||
wdump((int64_t(_block_num_to_pos.tellg())) );
|
||||
_block_num_to_pos.read( (char*)&e, sizeof(e) );
|
||||
wdump((block_num)(e));
|
||||
|
||||
vector<char> data( e.block_size );
|
||||
_blocks.seekg( e.block_pos );
|
||||
_blocks.read( data.data(), e.block_size );
|
||||
return fc::raw::unpack<signed_block>(data);
|
||||
}
|
||||
auto result = fc::raw::unpack<signed_block>(data);
|
||||
FC_ASSERT( result.id() == e.block_id );
|
||||
return result;
|
||||
} FC_CAPTURE_AND_RETHROW( (block_num) ) }
|
||||
|
||||
|
||||
optional<signed_block> block_database::last()const
|
||||
|
|
@ -145,14 +169,21 @@ optional<signed_block> block_database::last()const
|
|||
|
||||
_block_num_to_pos.seekg( -sizeof(index_entry), _block_num_to_pos.end );
|
||||
_block_num_to_pos.read( (char*)&e, sizeof(e) );
|
||||
|
||||
while( e.block_size == 0 && _blocks.tellg() > 0 )
|
||||
{
|
||||
_block_num_to_pos.seekg( -sizeof(index_entry), _block_num_to_pos.cur );
|
||||
_block_num_to_pos.read( (char*)&e, sizeof(e) );
|
||||
}
|
||||
|
||||
if( e.block_size == 0 )
|
||||
return optional<signed_block>();
|
||||
|
||||
vector<char> data( e.block_size );
|
||||
_blocks.seekg( e.block_pos );
|
||||
_blocks.read( data.data(), e.block_size );
|
||||
return fc::raw::unpack<signed_block>(data);
|
||||
auto result = fc::raw::unpack<signed_block>(data);
|
||||
wdump((result));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -84,7 +84,6 @@ bool database::push_block( const signed_block& new_block, uint32_t skip )
|
|||
{ try {
|
||||
if( !(skip&skip_fork_db) )
|
||||
{
|
||||
wdump((new_block.id())(new_block.previous));
|
||||
auto new_head = _fork_db.push_block( new_block );
|
||||
//If the head block from the longest chain does not build off of the current head, we need to switch forks.
|
||||
if( new_head->data.previous != head_block_id() )
|
||||
|
|
@ -115,12 +114,13 @@ bool database::push_block( const signed_block& new_block, uint32_t skip )
|
|||
try {
|
||||
auto session = _undo_db.start_undo_session();
|
||||
apply_block( (*ritr)->data, skip );
|
||||
_block_id_to_block.store( new_block.id(), (*ritr)->data );
|
||||
_block_id_to_block.store( (*ritr)->id, (*ritr)->data );
|
||||
session.commit();
|
||||
}
|
||||
catch ( const fc::exception& e ) { except = e; }
|
||||
if( except )
|
||||
{
|
||||
wdump((except->to_detail_string()));
|
||||
elog( "Encountered error when switching to a longer fork at id ${id}. Going back.",
|
||||
("id", (*ritr)->id) );
|
||||
// remove the rest of branches.first from the fork_db, those blocks are invalid
|
||||
|
|
@ -325,7 +325,7 @@ void database::apply_block( const signed_block& next_block, uint32_t skip )
|
|||
{ try {
|
||||
_applied_ops.clear();
|
||||
|
||||
FC_ASSERT( (skip & skip_merkle_check) || next_block.transaction_merkle_root == next_block.calculate_merkle_root() );
|
||||
FC_ASSERT( (skip & skip_merkle_check) || next_block.transaction_merkle_root == next_block.calculate_merkle_root(), "", ("next_block.transaction_merkle_root",next_block.transaction_merkle_root)("calc",next_block.calculate_merkle_root())("next_block",next_block)("id",next_block.id()) );
|
||||
|
||||
const witness_object& signing_witness = validate_block_header(skip, next_block);
|
||||
const auto& global_props = get_global_properties();
|
||||
|
|
|
|||
|
|
@ -41,7 +41,10 @@ void database::open( const fc::path& data_dir, const genesis_allocation& initial
|
|||
_block_id_to_block.open( data_dir / "database" / "block_num_to_block" );
|
||||
|
||||
if( !find(global_property_id_type()) )
|
||||
{
|
||||
ilog( "Init Genesis State" );
|
||||
init_genesis(initial_allocation);
|
||||
}
|
||||
|
||||
_pending_block.previous = head_block_id();
|
||||
_pending_block.timestamp = head_block_time();
|
||||
|
|
@ -96,6 +99,7 @@ void database::close(uint32_t blocks_to_rewind)
|
|||
for(uint32_t i = 0; i < blocks_to_rewind && head_block_num() > 0; ++i)
|
||||
pop_block();
|
||||
|
||||
object_database::flush();
|
||||
object_database::close();
|
||||
|
||||
if( _block_id_to_block.is_open() )
|
||||
|
|
|
|||
|
|
@ -177,7 +177,7 @@ namespace graphene { namespace db {
|
|||
virtual void set_next_id( object_id_type id )override { _next_id = id; }
|
||||
|
||||
virtual void open( const path& db )override
|
||||
{
|
||||
{
|
||||
if( !fc::exists( db ) ) return;
|
||||
fc::file_mapping fm( db.generic_string().c_str(), fc::read_only );
|
||||
fc::mapped_region mr( fm, fc::read_only, 0, fc::file_size(db) );
|
||||
|
|
@ -195,7 +195,9 @@ namespace graphene { namespace db {
|
|||
|
||||
virtual void save( const path& db ) override
|
||||
{
|
||||
std::ofstream out( db.generic_string(), std::ofstream::binary );
|
||||
std::ofstream out( db.generic_string(),
|
||||
std::ofstream::binary | std::ofstream::out | std::ofstream::trunc );
|
||||
FC_ASSERT( out );
|
||||
out.write( (char*)&_next_id, sizeof(_next_id) );
|
||||
this->inspect_all_objects( [&]( const object& o ) {
|
||||
auto vec = fc::raw::pack( static_cast<const object_type&>(o) );
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ void object_database::flush()
|
|||
ilog("Save object_database in ${d}", ("d", _data_dir));
|
||||
for( uint32_t space = 0; space < _index.size(); ++space )
|
||||
{
|
||||
fc::create_directories( _data_dir / "object_database" / fc::to_string(space) );
|
||||
const auto types = _index[space].size();
|
||||
for( uint32_t type = 0; type < types; ++type )
|
||||
if( _index[space][type] )
|
||||
|
|
|
|||
|
|
@ -37,6 +37,73 @@ using namespace graphene::chain;
|
|||
|
||||
BOOST_AUTO_TEST_SUITE(block_tests)
|
||||
|
||||
BOOST_AUTO_TEST_CASE( block_database_test )
|
||||
{
|
||||
try {
|
||||
fc::temp_directory data_dir;
|
||||
|
||||
block_database bdb;
|
||||
bdb.open( data_dir.path() );
|
||||
FC_ASSERT( bdb.is_open() );
|
||||
bdb.close();
|
||||
FC_ASSERT( !bdb.is_open() );
|
||||
bdb.open( data_dir.path() );
|
||||
|
||||
signed_block b;
|
||||
for( uint32_t i = 0; i < 5; ++i )
|
||||
{
|
||||
if( i > 0 ) b.previous = b.id();
|
||||
b.witness = witness_id_type(i+1);
|
||||
edump((b));
|
||||
bdb.store( b.id(), b );
|
||||
|
||||
auto fetch = bdb.fetch_by_number( b.block_num() );
|
||||
idump((fetch));
|
||||
FC_ASSERT( fetch.valid() );
|
||||
FC_ASSERT( fetch->witness == b.witness );
|
||||
fetch = bdb.fetch_by_number( i+1 );
|
||||
idump((fetch));
|
||||
FC_ASSERT( fetch.valid() );
|
||||
FC_ASSERT( fetch->witness == b.witness );
|
||||
fetch = bdb.fetch_optional( b.id() );
|
||||
idump((fetch));
|
||||
FC_ASSERT( fetch.valid() );
|
||||
FC_ASSERT( fetch->witness == b.witness );
|
||||
}
|
||||
ilog("-----------" );
|
||||
|
||||
for( uint32_t i = 1; i < 5; ++i )
|
||||
{
|
||||
auto blk = bdb.fetch_by_number( i );
|
||||
FC_ASSERT( blk.valid() );
|
||||
idump((blk)(i));
|
||||
FC_ASSERT( blk->witness == witness_id_type(blk->block_num()) );
|
||||
}
|
||||
|
||||
auto last = bdb.last();
|
||||
FC_ASSERT( last );
|
||||
FC_ASSERT( last->id() == b.id() );
|
||||
|
||||
bdb.close();
|
||||
bdb.open( data_dir.path() );
|
||||
last = bdb.last();
|
||||
FC_ASSERT( last );
|
||||
FC_ASSERT( last->id() == b.id() );
|
||||
|
||||
for( uint32_t i = 0; i < 5; ++i )
|
||||
{
|
||||
auto blk = bdb.fetch_by_number( i+1 );
|
||||
FC_ASSERT( blk.valid() );
|
||||
idump((blk)(i));
|
||||
FC_ASSERT( blk->witness == witness_id_type(blk->block_num()) );
|
||||
}
|
||||
|
||||
} catch (fc::exception& e) {
|
||||
edump((e.to_detail_string()));
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( generate_empty_blocks )
|
||||
{
|
||||
try {
|
||||
|
|
@ -142,7 +209,7 @@ BOOST_AUTO_TEST_CASE( fork_blocks )
|
|||
db2.open( data_dir2.path(), genesis_allocation() );
|
||||
|
||||
auto delegate_priv_key = fc::ecc::private_key::regenerate(fc::sha256::hash(string("genesis")) );
|
||||
for( uint32_t i = 0; i < 20; ++i )
|
||||
for( uint32_t i = 0; i < 10; ++i )
|
||||
{
|
||||
now += db1.block_interval();
|
||||
auto b = db1.generate_block( now, db1.get_scheduled_witness( 1 ).first, delegate_priv_key );
|
||||
|
|
@ -150,20 +217,19 @@ BOOST_AUTO_TEST_CASE( fork_blocks )
|
|||
db2.push_block(b);
|
||||
} FC_CAPTURE_AND_RETHROW( ("db2") );
|
||||
}
|
||||
for( uint32_t i = 20; i < 23; ++i )
|
||||
for( uint32_t i = 10; i < 13; ++i )
|
||||
{
|
||||
now += db1.block_interval();
|
||||
auto b = db1.generate_block( now, db1.get_scheduled_witness( 1 ).first, delegate_priv_key );
|
||||
}
|
||||
string db1_tip = db1.head_block_id().str();
|
||||
for( uint32_t i = 23; i < 26; ++i )
|
||||
for( uint32_t i = 13; i < 16; ++i )
|
||||
{
|
||||
now += db2.block_interval();
|
||||
auto b = db2.generate_block( now, db2.get_scheduled_witness( db2.get_slot_at_time( now ) ).first, delegate_priv_key );
|
||||
// notify both databases of the new block.
|
||||
// only db2 should switch to the new fork, db1 should not
|
||||
db1.push_block(b);
|
||||
db2.push_block(b);
|
||||
BOOST_CHECK_EQUAL(db1.head_block_id().str(), db1_tip);
|
||||
BOOST_CHECK_EQUAL(db2.head_block_id().str(), b.id().str());
|
||||
}
|
||||
|
|
@ -171,8 +237,8 @@ BOOST_AUTO_TEST_CASE( fork_blocks )
|
|||
//The two databases are on distinct forks now, but at the same height. Make a block on db2, make it invalid, then
|
||||
//pass it to db1 and assert that db1 doesn't switch to the new fork.
|
||||
signed_block good_block;
|
||||
BOOST_CHECK_EQUAL(db1.head_block_num(), 23);
|
||||
BOOST_CHECK_EQUAL(db2.head_block_num(), 23);
|
||||
BOOST_CHECK_EQUAL(db1.head_block_num(), 13);
|
||||
BOOST_CHECK_EQUAL(db2.head_block_num(), 13);
|
||||
{
|
||||
now += db2.block_interval();
|
||||
auto b = db2.generate_block( now, db2.get_scheduled_witness( 1 ).first, delegate_priv_key );
|
||||
|
|
@ -180,14 +246,14 @@ BOOST_AUTO_TEST_CASE( fork_blocks )
|
|||
b.transactions.emplace_back(signed_transaction());
|
||||
b.transactions.back().operations.emplace_back(transfer_operation());
|
||||
b.sign(delegate_priv_key);
|
||||
BOOST_CHECK_EQUAL(b.block_num(), 24);
|
||||
BOOST_CHECK_EQUAL(b.block_num(), 14);
|
||||
BOOST_CHECK_THROW(db1.push_block(b), fc::exception);
|
||||
}
|
||||
BOOST_CHECK_EQUAL(db1.head_block_num(), 23);
|
||||
BOOST_CHECK_EQUAL(db1.head_block_num(), 13);
|
||||
BOOST_CHECK_EQUAL(db1.head_block_id().str(), db1_tip);
|
||||
|
||||
// assert that db1 switches to new fork with good block
|
||||
BOOST_CHECK_EQUAL(db2.head_block_num(), 24);
|
||||
BOOST_CHECK_EQUAL(db2.head_block_num(), 14);
|
||||
db1.push_block(good_block);
|
||||
BOOST_CHECK_EQUAL(db1.head_block_id().str(), db2.head_block_id().str());
|
||||
} catch (fc::exception& e) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue