diff --git a/libraries/chain/database.cpp b/libraries/chain/database.cpp index d23d19496e6..10d78d0c990 100644 --- a/libraries/chain/database.cpp +++ b/libraries/chain/database.cpp @@ -61,26 +61,35 @@ bool database::is_known_transaction( const transaction_id_type& id )const return trx_idx.find( id ) != trx_idx.end(); } -block_id_type database::get_block_id_for_num( uint32_t block_num )const +block_id_type database::get_block_id_for_num(uint32_t block_num)const { try { - return _block_id_to_block.fetch_block_id( block_num ); -} FC_CAPTURE_AND_RETHROW( (block_num) ) } + if (const auto& block = fetch_block_by_number(block_num)) + return block->id(); -optional database::fetch_block_by_id( const block_id_type& id )const + FC_THROW_EXCEPTION(unknown_block_exception, "Could not find block"); +} FC_CAPTURE_AND_RETHROW((block_num)) } + +optional database::fetch_block_by_id(const block_id_type& id)const { - auto b = _fork_db.fetch_block( id ); - if( !b ) - return _block_id_to_block.fetch_optional(id); - return b->data; + auto b = _fork_db.fetch_block(id); + if(b) return b->data; + return _block_id_to_block.fetch_optional(id); } optional database::fetch_block_by_number( uint32_t num )const { - auto results = _fork_db.fetch_block_by_number(num); - if( results.size() == 1 ) - return results[0]->data; - else - return _block_id_to_block.fetch_by_number(num); + if (const auto& block = _block_id_to_block.fetch_by_number(num)) + return *block; + + // Not in _block_id_to_block, so it must be since the last irreversible block. Grab it from _fork_db instead + if (num <= head_block_num()) { + auto block = _fork_db.head(); + while (block && block->num > num) + block = block->prev.lock(); + if (block && block->num == num) + return block->data; + } + return optional(); } diff --git a/libraries/chain/include/eos/chain/exceptions.hpp b/libraries/chain/include/eos/chain/exceptions.hpp index f3a023100c6..63c302b8751 100644 --- a/libraries/chain/include/eos/chain/exceptions.hpp +++ b/libraries/chain/include/eos/chain/exceptions.hpp @@ -77,6 +77,7 @@ namespace eos { namespace chain { FC_DECLARE_DERIVED_EXCEPTION( undo_database_exception, eos::chain::chain_exception, 3070000, "undo database exception" ) FC_DECLARE_DERIVED_EXCEPTION( unlinkable_block_exception, eos::chain::chain_exception, 3080000, "unlinkable block" ) FC_DECLARE_DERIVED_EXCEPTION( black_swan_exception, eos::chain::chain_exception, 3090000, "black swan" ) + FC_DECLARE_DERIVED_EXCEPTION( unknown_block_exception, eos::chain::chain_exception, 3100000, "unknown block" ) FC_DECLARE_DERIVED_EXCEPTION( tx_missing_active_auth, eos::chain::transaction_exception, 3030001, "missing required active authority" ) FC_DECLARE_DERIVED_EXCEPTION( tx_missing_owner_auth, eos::chain::transaction_exception, 3030002, "missing required owner authority" ) @@ -119,7 +120,6 @@ namespace eos { namespace chain { FC_DECLARE_DERIVED_EXCEPTION( invalid_committee_member_signee, eos::chain::chain_exception, 30021, "invalid committee_member signee" ) FC_DECLARE_DERIVED_EXCEPTION( failed_checkpoint_verification, eos::chain::chain_exception, 30022, "failed checkpoint verification" ) FC_DECLARE_DERIVED_EXCEPTION( wrong_chain_id, eos::chain::chain_exception, 30023, "wrong chain id" ) - FC_DECLARE_DERIVED_EXCEPTION( unknown_block, eos::chain::chain_exception, 30024, "unknown block" ) FC_DECLARE_DERIVED_EXCEPTION( block_older_than_undo_history, eos::chain::chain_exception, 30025, "block is older than our undo history allows us to process" ) FC_DECLARE_EXCEPTION( evaluation_error, 31000, "Evaluation Error" ) diff --git a/tests/tests/database_tests.cpp b/tests/tests/database_tests.cpp index 61ee4e5eb82..3a1bcee81c1 100644 --- a/tests/tests/database_tests.cpp +++ b/tests/tests/database_tests.cpp @@ -22,14 +22,13 @@ * THE SOFTWARE. */ -#include - #include - #include #include +#include + #include "../common/database_fixture.hpp" using namespace eos::chain; @@ -58,3 +57,48 @@ BOOST_FIXTURE_TEST_CASE(undo_test, testing_fixture) throw; } } + +BOOST_FIXTURE_TEST_CASE(get_blocks, testing_fixture) +{ try { + MKDB(db) + + // I apologize if this proves fragile in the future. Any changes to how block IDs are calculated, or producer + // scheduling, etc. will break this, but hopefully it should be pretty easy to just swap in the new IDs... :] + block_id_type block_ids[] = { + block_id_type("0000000130e605ebe8ba3da0d5d1ed556ccfde3b"), + block_id_type("00000002a23c51a99d8d32b671012ebc221a4098"), + block_id_type("00000003eaf03b2aca76f64db5e640325c0e7b3f"), + block_id_type("000000041e533056ead792fd5935d23c84311b30"), + block_id_type("000000058aa9a6436929741ffee02fed1f2b4290"), + block_id_type("000000063037551d2353ffb0ab07a9b5e582e66b"), + block_id_type("00000007f3960fb247bd95feb9280565b4a0eb2e"), + block_id_type("0000000893bd630f901ff78bd5d5a28574698f45"), + block_id_type("0000000928143087ee97d5429be8282b1ce2d323"), + block_id_type("0000000a3b9c0c3a596069f36f678f0e69a6a7a4"), + block_id_type("0000000bf05985672af3481f1f1c780ac40b1299"), + block_id_type("0000000c6665f984a6e994c7732255aaab25dee2"), + block_id_type("0000000d3cf47c047f681451508efd07d418574c"), + block_id_type("0000000e62d6764b69c4d2bb72047676bfff5e79"), + block_id_type("0000000f85aa69d6f5d900e3e26daf5f19d91d91"), + block_id_type("000000106c1e81538bf6ce21e9d000d7c9beb20e"), + block_id_type("00000011cd6a0d410addfdf8c7816c168e24af6e"), + block_id_type("000000120b333f3264d605127b50e28b9679279f"), + block_id_type("000000138983847a10b1dc66503c556e9e66f461"), + block_id_type("0000001420541bed52c10949a82c5d0b311fb489") + }; + + db.produce_blocks(20); + for (int i = 0; i < 20; ++i) { + BOOST_CHECK(db.is_known_block(block_ids[i])); + BOOST_CHECK_EQUAL(db.get_block_id_for_num(i+1), block_ids[i]); + BOOST_CHECK_EQUAL(db.fetch_block_by_id(block_ids[i])->block_num(), i+1); + BOOST_CHECK_EQUAL(db.fetch_block_by_number(i+1)->id(), block_ids[i]); + } + + BOOST_CHECK_EQUAL(db.last_irreversible_block_num(), 13); + BOOST_CHECK_THROW(db.get_block_id_for_num(21), eos::chain::unknown_block_exception); + + db.produce_blocks(); + BOOST_CHECK_EQUAL(db.last_irreversible_block_num(), 14); + BOOST_CHECK_EQUAL(db.get_block_id_for_num(21), db.head_block_id()); +} FC_LOG_AND_RETHROW() }