Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Extend get_block_header API and get_block_header_batch API to optionally return witness signatures #2652

Merged
merged 3 commits into from
Oct 7, 2022
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions libraries/app/api_objects.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,4 +130,10 @@ market_ticker::market_ticker(const fc::time_point_sec& now,
quote_volume = "0";
}

maybe_signed_block_header::maybe_signed_block_header( const signed_block_header& bh, bool with_witness_signature )
: block_header( bh ), // Slice intentionally
witness_signature( with_witness_signature ? bh.witness_signature : optional<signature_type>() )
{ // Nothing else to do
}

} } // graphene::app
27 changes: 16 additions & 11 deletions libraries/app/database_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -227,31 +227,36 @@ void database_api_impl::cancel_all_subscriptions( bool reset_callback, bool rese
// //
//////////////////////////////////////////////////////////////////////

optional<signed_block_header> database_api::get_block_header(uint32_t block_num)const
optional<maybe_signed_block_header> database_api::get_block_header(
uint32_t block_num, const optional<bool>& with_witness_signature )const
{
return my->get_block_header( block_num );
bool with_signature = ( with_witness_signature.valid() && *with_witness_signature );
return my->get_block_header( block_num, with_signature );
}

optional<signed_block_header> database_api_impl::get_block_header(uint32_t block_num) const
optional<maybe_signed_block_header> database_api_impl::get_block_header(
uint32_t block_num, bool with_witness_signature )const
{
auto result = _db.fetch_block_by_number(block_num);
if(result)
return *result;
return maybe_signed_block_header( *result, with_witness_signature );
return {};
}
map<uint32_t, optional<signed_block_header>> database_api::get_block_header_batch(
const vector<uint32_t>& block_nums) const

map<uint32_t, optional<maybe_signed_block_header>> database_api::get_block_header_batch(
const vector<uint32_t>& block_nums, const optional<bool>& with_witness_signatures )const
{
return my->get_block_header_batch( block_nums );
bool with_signatures = ( with_witness_signatures.valid() && *with_witness_signatures );
return my->get_block_header_batch( block_nums, with_signatures );
}

map<uint32_t, optional<signed_block_header>> database_api_impl::get_block_header_batch(
const vector<uint32_t>& block_nums) const
map<uint32_t, optional<maybe_signed_block_header>> database_api_impl::get_block_header_batch(
const vector<uint32_t>& block_nums, bool with_witness_signatures )const
{
map<uint32_t, optional<signed_block_header>> results;
map<uint32_t, optional<maybe_signed_block_header>> results;
for (const uint32_t block_num : block_nums)
{
results[block_num] = get_block_header(block_num);
results[block_num] = get_block_header( block_num, with_witness_signatures );
}
return results;
}
Expand Down
5 changes: 3 additions & 2 deletions libraries/app/database_api_impl.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,9 @@ class database_api_impl : public std::enable_shared_from_this<database_api_impl>
void cancel_all_subscriptions(bool reset_callback, bool reset_market_subscriptions);

// Blocks and transactions
optional<signed_block_header> get_block_header(uint32_t block_num)const;
map<uint32_t, optional<signed_block_header>> get_block_header_batch(const vector<uint32_t>& block_nums)const;
optional<maybe_signed_block_header> get_block_header( uint32_t block_num, bool with_witness_signature )const;
map<uint32_t, optional<maybe_signed_block_header>> get_block_header_batch(
const vector<uint32_t>& block_nums, bool with_witness_signatures )const;
optional<signed_block> get_block(uint32_t block_num)const;
processed_transaction get_transaction( uint32_t block_num, uint32_t trx_in_block )const;

Expand Down
10 changes: 10 additions & 0 deletions libraries/app/include/graphene/app/api_objects.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,14 @@ namespace graphene { namespace app {
optional<liquidity_pool_ticker_object> statistics;
};

struct maybe_signed_block_header : block_header
{
maybe_signed_block_header() = default;
explicit maybe_signed_block_header( const signed_block_header& bh, bool with_witness_signature = true );

optional<signature_type> witness_signature;
};

} }

FC_REFLECT( graphene::app::more_data,
Expand Down Expand Up @@ -221,3 +229,5 @@ FC_REFLECT_DERIVED( graphene::app::extended_asset_object, (graphene::chain::asse
FC_REFLECT_DERIVED( graphene::app::extended_liquidity_pool_object, (graphene::chain::liquidity_pool_object),
(statistics) )

FC_REFLECT_DERIVED( graphene::app::maybe_signed_block_header, (graphene::protocol::block_header),
(witness_signature) )
22 changes: 15 additions & 7 deletions libraries/app/include/graphene/app/database_api.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,18 +153,26 @@ class database_api
/////////////////////////////

/**
* @brief Retrieve a signed block header
* @brief Retrieve a block header
* @param block_num Height of the block whose header should be returned
* @param with_witness_signature Whether to return witness signature. Optional.
* If omitted or is @a false, will not return witness signature.
* @return header of the referenced block, or null if no matching block was found
*/
optional<signed_block_header> get_block_header(uint32_t block_num)const;
optional<maybe_signed_block_header> get_block_header(
uint32_t block_num,
const optional<bool>& with_witness_signature = optional<bool>() )const;

/**
* @brief Retrieve multiple signed block headers by block numbers
* @param block_nums vector containing heights of the blocks whose headers should be returned
* @return array of headers of the referenced blocks, or null if no matching block was found
*/
map<uint32_t, optional<signed_block_header>> get_block_header_batch(const vector<uint32_t>& block_nums)const;
* @brief Retrieve multiple block headers by block numbers
* @param block_nums vector containing heights of the blocks whose headers should be returned
* @param with_witness_signatures Whether to return witness signatures. Optional.
* If omitted or is @a false, will not return witness signatures.
* @return array of headers of the referenced blocks, or null if no matching block was found
*/
map<uint32_t, optional<maybe_signed_block_header>> get_block_header_batch(
const vector<uint32_t>& block_nums,
const optional<bool>& with_witness_signatures = optional<bool>() )const;

/**
* @brief Retrieve a full, signed block
Expand Down
5 changes: 5 additions & 0 deletions libraries/protocol/include/graphene/protocol/block.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ namespace graphene { namespace protocol {
// More info in https://github.com/bitshares/bitshares-core/issues/1136
extensions_type extensions;

virtual ~block_header() = default;

static uint32_t num_from_id(const block_id_type& id);
};

Expand All @@ -51,6 +53,9 @@ namespace graphene { namespace protocol {
bool validate_signee( const fc::ecc::public_key& expected_signee )const;

signature_type witness_signature;

signed_block_header() = default;
explicit signed_block_header( const block_header& header ) : block_header( header ) {}
protected:
mutable fc::ecc::public_key _signee;
mutable block_id_type _block_id;
Expand Down
90 changes: 77 additions & 13 deletions tests/tests/database_api_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1483,6 +1483,14 @@ BOOST_AUTO_TEST_CASE( get_transaction_hex )
BOOST_AUTO_TEST_CASE( get_block_tests )
{ try {

const auto& get_block_id = []( const graphene::app::maybe_signed_block_header& header )
{
signed_block_header signed_header( static_cast<block_header>( header ) );
if( header.witness_signature.valid() )
signed_header.witness_signature = *header.witness_signature;
return signed_header.id();
};

generate_block();

ACTORS( (nathan) );
Expand All @@ -1505,11 +1513,35 @@ BOOST_AUTO_TEST_CASE( get_block_tests )
BOOST_CHECK( head_block->witness_signature != signature_type() );
BOOST_CHECK( head_block->id() == block3.id() );

auto head_block_header = db_api.get_block_header( head_block_num );
auto head_block_header = db_api.get_block_header( head_block_num, true );
idump( (head_block_header) );
BOOST_REQUIRE( head_block_header.valid() );
BOOST_CHECK_EQUAL( head_block_header->block_num(), head_block_num );
BOOST_CHECK( head_block_header->witness_signature == head_block->witness_signature );
BOOST_CHECK( head_block_header->id() == head_block->id() );
BOOST_REQUIRE( head_block_header->witness_signature.valid() );
BOOST_CHECK( *head_block_header->witness_signature == head_block->witness_signature );
BOOST_CHECK( get_block_id( *head_block_header ) == head_block->id() );

auto head_block_header2 = db_api.get_block_header( head_block_num );
idump( (head_block_header2) );
BOOST_REQUIRE( head_block_header2.valid() );
BOOST_CHECK_EQUAL( head_block_header2->block_num(), head_block_num );
BOOST_CHECK( head_block_header2->previous == head_block->previous );
BOOST_CHECK( head_block_header2->timestamp == head_block->timestamp );
BOOST_CHECK( head_block_header2->witness == head_block->witness );
BOOST_CHECK( head_block_header2->transaction_merkle_root == head_block->transaction_merkle_root );
BOOST_CHECK( !head_block_header2->witness_signature.valid() );
BOOST_CHECK( get_block_id( *head_block_header2 ) != head_block->id() );

auto head_block_header3 = db_api.get_block_header( head_block_num, false );
idump( (head_block_header3) );
BOOST_REQUIRE( head_block_header3.valid() );
BOOST_CHECK_EQUAL( head_block_header3->block_num(), head_block_num );
BOOST_CHECK( head_block_header3->previous == head_block->previous );
BOOST_CHECK( head_block_header3->timestamp == head_block->timestamp );
BOOST_CHECK( head_block_header3->witness == head_block->witness );
BOOST_CHECK( head_block_header3->transaction_merkle_root == head_block->transaction_merkle_root );
BOOST_CHECK( !head_block_header3->witness_signature.valid() );
BOOST_CHECK( get_block_id( *head_block_header3 ) == get_block_id( *head_block_header2 ) );

auto previous_block = db_api.get_block( head_block_num - 1 );
BOOST_REQUIRE( previous_block.valid() );
Expand All @@ -1520,31 +1552,63 @@ BOOST_AUTO_TEST_CASE( get_block_tests )
BOOST_CHECK( previous_block->witness_signature != head_block->witness_signature );
BOOST_CHECK( previous_block->id() == block2.id() );

auto previous_block_header = db_api.get_block_header( head_block_num - 1 );
auto previous_block_header = db_api.get_block_header( head_block_num - 1, true );
BOOST_REQUIRE( previous_block_header.valid() );
BOOST_CHECK_EQUAL( previous_block_header->block_num(), head_block_num - 1 );
BOOST_CHECK( previous_block_header->witness_signature == previous_block->witness_signature );
BOOST_CHECK( previous_block_header->id() == previous_block->id() );
BOOST_REQUIRE( previous_block_header->witness_signature.valid() );
BOOST_CHECK( *previous_block_header->witness_signature == previous_block->witness_signature );
BOOST_CHECK( get_block_id( *previous_block_header ) == previous_block->id() );

auto next_block = db_api.get_block( head_block_num + 1 );
BOOST_CHECK( !next_block.valid() );

auto next_block_header = db_api.get_block_header( head_block_num + 1 );
auto next_block_header = db_api.get_block_header( head_block_num + 1, true );
BOOST_CHECK( !next_block_header.valid() );

const auto block_headers = db_api.get_block_header_batch( { head_block_num, head_block_num + 1,
head_block_num - 1 } );
head_block_num - 1 }, true );
BOOST_REQUIRE_EQUAL( block_headers.size(), 3U );
BOOST_CHECK_THROW( block_headers.at( head_block_num + 2 ), std::out_of_range );
BOOST_CHECK( !block_headers.at( head_block_num + 1 ).valid() );
BOOST_REQUIRE( block_headers.at( head_block_num ).valid() );
BOOST_CHECK( block_headers.at( head_block_num )->block_num() == head_block_header->block_num() );
BOOST_CHECK( block_headers.at( head_block_num )->id() == head_block_header->id() );
BOOST_CHECK( block_headers.at( head_block_num )->witness_signature == head_block_header->witness_signature );
BOOST_CHECK( get_block_id( *block_headers.at( head_block_num ) ) == head_block->id() );
BOOST_REQUIRE( block_headers.at( head_block_num )->witness_signature.valid() );
BOOST_CHECK( *block_headers.at( head_block_num )->witness_signature == head_block->witness_signature );
BOOST_REQUIRE( block_headers.at( head_block_num - 1 ).valid() );
BOOST_CHECK( block_headers.at( head_block_num - 1 )->block_num() == previous_block_header->block_num() );
BOOST_CHECK( block_headers.at( head_block_num - 1 )->id() == previous_block_header->id() );
BOOST_CHECK( block_headers.at( head_block_num - 1 )->witness_signature
== previous_block_header->witness_signature );
BOOST_CHECK( get_block_id( *block_headers.at( head_block_num - 1 ) ) == previous_block->id() );
BOOST_REQUIRE( block_headers.at( head_block_num - 1 )->witness_signature.valid() );
BOOST_CHECK( *block_headers.at( head_block_num - 1 )->witness_signature == previous_block->witness_signature );

const auto block_headers2 = db_api.get_block_header_batch( { head_block_num, head_block_num + 1,
head_block_num - 1 } );
BOOST_REQUIRE_EQUAL( block_headers2.size(), 3U );
BOOST_CHECK_THROW( block_headers2.at( head_block_num + 2 ), std::out_of_range );
BOOST_CHECK( !block_headers2.at( head_block_num + 1 ).valid() );
BOOST_REQUIRE( block_headers2.at( head_block_num ).valid() );
BOOST_CHECK( block_headers2.at( head_block_num )->block_num() == head_block_header->block_num() );
BOOST_CHECK( get_block_id( *block_headers2.at( head_block_num ) ) == get_block_id( *head_block_header2 ) );
BOOST_CHECK( !block_headers2.at( head_block_num )->witness_signature.valid() );
BOOST_REQUIRE( block_headers2.at( head_block_num - 1 ).valid() );
BOOST_CHECK( block_headers2.at( head_block_num - 1 )->block_num() == previous_block_header->block_num() );
BOOST_CHECK( get_block_id( *block_headers2.at( head_block_num - 1 ) ) != previous_block->id() );
BOOST_CHECK( !block_headers2.at( head_block_num - 1 )->witness_signature.valid() );

const auto block_headers3 = db_api.get_block_header_batch( { head_block_num, head_block_num + 1,
head_block_num - 1 }, false );
BOOST_REQUIRE_EQUAL( block_headers3.size(), 3U );
BOOST_CHECK_THROW( block_headers3.at( head_block_num + 2 ), std::out_of_range );
BOOST_CHECK( !block_headers3.at( head_block_num + 1 ).valid() );
BOOST_REQUIRE( block_headers3.at( head_block_num ).valid() );
BOOST_CHECK( block_headers3.at( head_block_num )->block_num() == head_block_header->block_num() );
BOOST_CHECK( get_block_id( *block_headers3.at( head_block_num ) ) == get_block_id( *head_block_header2 ) );
BOOST_CHECK( !block_headers3.at( head_block_num )->witness_signature.valid() );
BOOST_REQUIRE( block_headers3.at( head_block_num - 1 ).valid() );
BOOST_CHECK( block_headers3.at( head_block_num - 1 )->block_num() == previous_block_header->block_num() );
BOOST_CHECK( get_block_id( *block_headers3.at( head_block_num - 1 ) )
== get_block_id( *block_headers2.at( head_block_num - 1 ) ) );
BOOST_CHECK( !block_headers3.at( head_block_num - 1 )->witness_signature.valid() );

} FC_LOG_AND_RETHROW() }

Expand Down