Skip to content

Commit

Permalink
Merge pull request #2652 from bitshares/pr-2588-optional-sigs
Browse files Browse the repository at this point in the history
Extend get_block_header API and get_block_header_batch API to optionally return witness signatures
  • Loading branch information
abitmore authored Oct 7, 2022
2 parents 938cfee + 43c95ab commit 0883cad
Show file tree
Hide file tree
Showing 7 changed files with 132 additions and 33 deletions.
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

0 comments on commit 0883cad

Please # to comment.