Skip to content

Commit

Permalink
Merge pull request #820 from AntelopeIO/huangminghuang/get_raw_block
Browse files Browse the repository at this point in the history
get_raw_block api endpoint
  • Loading branch information
huangminghuang authored Mar 16, 2023
2 parents d4ffa14 + af1dcf2 commit 326c169
Show file tree
Hide file tree
Showing 11 changed files with 200 additions and 44 deletions.
35 changes: 21 additions & 14 deletions libraries/chain/block_log.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,15 +185,15 @@ namespace eosio { namespace chain {
}

template <typename Stream>
block_id_type read_block_id(Stream&& ds, uint32_t expect_block_num) {
block_header bh;
signed_block_header read_block_header(Stream&& ds, uint32_t expect_block_num) {
signed_block_header bh;
fc::raw::unpack(ds, bh);

EOS_ASSERT(bh.block_num() == expect_block_num, block_log_exception,
"Wrong block header was read from block log.",
("returned", bh.block_num())("expected", expect_block_num));

return bh.calculate_id();
return bh;
}

/// Provide the read only view of the blocks.log file
Expand Down Expand Up @@ -474,8 +474,8 @@ namespace eosio { namespace chain {
virtual void reset(const chain_id_type& chain_id, uint32_t first_block_num) = 0;
virtual void flush() = 0;

virtual signed_block_ptr read_block_by_num(uint32_t block_num) = 0;
virtual block_id_type read_block_id_by_num(uint32_t block_num) = 0;
virtual signed_block_ptr read_block_by_num(uint32_t block_num) = 0;
virtual std::optional<signed_block_header> read_block_header_by_num(uint32_t block_num) = 0;

virtual uint32_t version() const = 0;

Expand Down Expand Up @@ -512,7 +512,7 @@ namespace eosio { namespace chain {
void flush() final {}

signed_block_ptr read_block_by_num(uint32_t block_num) final { return {}; };
block_id_type read_block_id_by_num(uint32_t block_num) final { return {}; };
std::optional<signed_block_header> read_block_header_by_num(uint32_t block_num) final { return {}; };

uint32_t version() const final { return 0; }
signed_block_ptr read_head() final { return {}; };
Expand Down Expand Up @@ -556,7 +556,7 @@ namespace eosio { namespace chain {
virtual uint32_t working_block_file_first_block_num() { return preamble.first_block_num; }
virtual void post_append(uint64_t pos) {}
virtual signed_block_ptr retry_read_block_by_num(uint32_t block_num) { return {}; }
virtual block_id_type retry_read_block_id_by_num(uint32_t block_num) { return {}; }
virtual std::optional<signed_block_header> retry_read_block_header_by_num(uint32_t block_num) { return {}; }

void append(const signed_block_ptr& b, const block_id_type& id,
const std::vector<char>& packed_block) override {
Expand Down Expand Up @@ -609,14 +609,14 @@ namespace eosio { namespace chain {
FC_LOG_AND_RETHROW()
}

block_id_type read_block_id_by_num(uint32_t block_num) final {
std::optional<signed_block_header> read_block_header_by_num(uint32_t block_num) final {
try {
uint64_t pos = get_block_pos(block_num);
if (pos != block_log::npos) {
block_file.seek(pos);
return read_block_id(block_file, block_num);
return read_block_header(block_file, block_num);
}
return retry_read_block_id_by_num(block_num);
return retry_read_block_header_by_num(block_num);
}
FC_LOG_AND_RETHROW()
}
Expand Down Expand Up @@ -1027,10 +1027,10 @@ namespace eosio { namespace chain {
return {};
}

block_id_type retry_read_block_id_by_num(uint32_t block_num) final {
std::optional<signed_block_header> retry_read_block_header_by_num(uint32_t block_num) final {
auto ds = catalog.ro_stream_for_block(block_num);
if (ds)
return read_block_id(*ds, block_num);
return read_block_header(*ds, block_num);
return {};
}

Expand Down Expand Up @@ -1225,9 +1225,16 @@ namespace eosio { namespace chain {
return my->read_block_by_num(block_num);
}

block_id_type block_log::read_block_id_by_num(uint32_t block_num) const {
std::optional<signed_block_header> block_log::read_block_header_by_num(uint32_t block_num) const {
std::lock_guard g(my->mtx);
return my->read_block_id_by_num(block_num);
return my->read_block_header_by_num(block_num);
}

block_id_type block_log::read_block_id_by_num(uint32_t block_num) const {
// read_block_header_by_num acquires mutex
auto bh = read_block_header_by_num(block_num);
if (bh) { return bh->calculate_id(); }
return {};
}

uint64_t block_log::get_block_pos(uint32_t block_num) const {
Expand Down
19 changes: 18 additions & 1 deletion libraries/chain/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3145,14 +3145,22 @@ const global_property_object& controller::get_global_properties()const {
return my->db.get<global_property_object>();
}

signed_block_ptr controller::fetch_block_by_id( block_id_type id )const {
signed_block_ptr controller::fetch_block_by_id( const block_id_type& id )const {
auto state = my->fork_db.get_block(id);
if( state && state->block ) return state->block;
auto bptr = my->blog.read_block_by_num( block_header::num_from_id(id) );
if( bptr && bptr->calculate_id() == id ) return bptr;
return signed_block_ptr();
}

std::optional<signed_block_header> controller::fetch_block_header_by_id( const block_id_type& id )const {
auto state = my->fork_db.get_block(id);
if( state && state->block ) return state->header;
auto result = my->blog.read_block_header_by_num( block_header::num_from_id(id) );
if( result && result->calculate_id() == id ) return result;
return {};
}

signed_block_ptr controller::fetch_block_by_number( uint32_t block_num )const { try {
auto blk_state = fetch_block_state_by_number( block_num );
if( blk_state ) {
Expand All @@ -3162,6 +3170,15 @@ signed_block_ptr controller::fetch_block_by_number( uint32_t block_num )const {
return my->blog.read_block_by_num(block_num);
} FC_CAPTURE_AND_RETHROW( (block_num) ) }

std::optional<signed_block_header> controller::fetch_block_header_by_number( uint32_t block_num )const { try {
auto blk_state = fetch_block_state_by_number( block_num );
if( blk_state ) {
return blk_state->header;
}

return my->blog.read_block_header_by_num(block_num);
} FC_CAPTURE_AND_RETHROW( (block_num) ) }

block_state_ptr controller::fetch_block_state_by_id( block_id_type id )const {
auto state = my->fork_db.get_block(id);
return state;
Expand Down
1 change: 1 addition & 0 deletions libraries/chain/include/eosio/chain/block_log.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ namespace eosio { namespace chain {
void reset( const chain_id_type& chain_id, uint32_t first_block_num );

signed_block_ptr read_block_by_num(uint32_t block_num)const;
std::optional<signed_block_header> read_block_header_by_num(uint32_t block_num)const;
block_id_type read_block_id_by_num(uint32_t block_num)const;

signed_block_ptr read_block_by_id(const block_id_type& id)const {
Expand Down
6 changes: 5 additions & 1 deletion libraries/chain/include/eosio/chain/controller.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,11 @@ namespace eosio { namespace chain {
// thread-safe
signed_block_ptr fetch_block_by_number( uint32_t block_num )const;
// thread-safe
signed_block_ptr fetch_block_by_id( block_id_type id )const;
signed_block_ptr fetch_block_by_id( const block_id_type& id )const;
// thread-safe
std::optional<signed_block_header> fetch_block_header_by_number( uint32_t block_num )const;
// thread-safe
std::optional<signed_block_header> fetch_block_header_by_id( const block_id_type& id )const;
// return block_state from forkdb, thread-safe
block_state_ptr fetch_block_state_by_number( uint32_t block_num )const;
// return block_state from forkdb, thread-safe
Expand Down
9 changes: 7 additions & 2 deletions plugins/chain_api_plugin/chain_api_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,11 @@ void chain_api_plugin::plugin_startup() {
});
}

_http_plugin.add_async_api({
CHAIN_RO_CALL_WITH_400(get_raw_block, 200, http_params_types::params_required),
CHAIN_RO_CALL_WITH_400(get_block_header, 200, http_params_types::params_required)
});

if (chain.transaction_finality_status_enabled()) {
_http_plugin.add_api({
CHAIN_RO_CALL_WITH_400(get_transaction_status, 200, http_params_types::params_required),
Expand All @@ -129,9 +134,9 @@ void chain_api_plugin::plugin_startup() {
auto deadline = ro_api.start();
try {
auto start = fc::time_point::now();
auto params = parse_params<chain_apis::read_only::get_block_params, http_params_types::params_required>(body);
auto params = parse_params<chain_apis::read_only::get_raw_block_params, http_params_types::params_required>(body);
FC_CHECK_DEADLINE( deadline );
chain::signed_block_ptr block = ro_api.get_block( params, deadline );
chain::signed_block_ptr block = ro_api.get_raw_block( params, deadline );

auto abi_cache = ro_api.get_block_serializers( block, max_time );
FC_CHECK_DEADLINE( deadline );
Expand Down
45 changes: 43 additions & 2 deletions plugins/chain_plugin/chain_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1903,13 +1903,13 @@ read_only::get_scheduled_transactions( const read_only::get_scheduled_transactio
return result;
}

chain::signed_block_ptr read_only::get_block(const read_only::get_block_params& params, const fc::time_point& deadline) const {
chain::signed_block_ptr read_only::get_raw_block(const read_only::get_raw_block_params& params, const fc::time_point& deadline) const {
signed_block_ptr block;
std::optional<uint64_t> block_num;

EOS_ASSERT( !params.block_num_or_id.empty() && params.block_num_or_id.size() <= 64,
chain::block_id_type_exception,
"Invalid Block number or ID, must be greater than 0 and less than 64 characters"
"Invalid Block number or ID, must be greater than 0 and less than 65 characters"
);

try {
Expand All @@ -1930,6 +1930,47 @@ chain::signed_block_ptr read_only::get_block(const read_only::get_block_params&
return block;
}

read_only::get_block_header_result read_only::get_block_header(const read_only::get_block_header_params& params, const fc::time_point& deadline) const{
std::optional<uint64_t> block_num;

EOS_ASSERT( !params.block_num_or_id.empty() && params.block_num_or_id.size() <= 64,
chain::block_id_type_exception,
"Invalid Block number or ID, must be greater than 0 and less than 65 characters"
);

try {
block_num = fc::to_uint64(params.block_num_or_id);
} catch( ... ) {}

if (!params.include_extensions) {
std::optional<signed_block_header> header;

if( block_num ) {
header = db.fetch_block_header_by_number( *block_num );
} else {
try {
header = db.fetch_block_header_by_id( fc::variant(params.block_num_or_id).as<block_id_type>() );
} EOS_RETHROW_EXCEPTIONS(chain::block_id_type_exception, "Invalid block ID: ${block_num_or_id}", ("block_num_or_id", params.block_num_or_id))
}
EOS_ASSERT( header, unknown_block_exception, "Could not find block header: ${block}", ("block", params.block_num_or_id));
return { header->calculate_id(), fc::variant{*header}, {}};
} else {
signed_block_ptr block;
if( block_num ) {
block = db.fetch_block_by_number( *block_num );
} else {
try {
block = db.fetch_block_by_id( fc::variant(params.block_num_or_id).as<block_id_type>() );
} EOS_RETHROW_EXCEPTIONS(chain::block_id_type_exception, "Invalid block ID: ${block_num_or_id}", ("block_num_or_id", params.block_num_or_id))
}
EOS_ASSERT( block, unknown_block_exception, "Could not find block header: ${block}", ("block", params.block_num_or_id));
return { block->calculate_id(), fc::variant{static_cast<signed_block_header>(*block)}, block->block_extensions};
}

FC_CHECK_DEADLINE(deadline);

}

std::unordered_map<account_name, std::optional<abi_serializer>>
read_only::get_block_serializers( const chain::signed_block_ptr& block, const fc::microseconds& max_time ) const {
auto yield = abi_serializer::create_yield_function( max_time );
Expand Down
25 changes: 20 additions & 5 deletions plugins/chain_plugin/include/eosio/chain_plugin/chain_plugin.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -325,11 +325,11 @@ class read_only {

get_transaction_id_result get_transaction_id( const get_transaction_id_params& params, const fc::time_point& deadline)const;

struct get_block_params {
struct get_raw_block_params {
string block_num_or_id;
};

chain::signed_block_ptr get_block(const get_block_params& params, const fc::time_point& deadline) const;
chain::signed_block_ptr get_raw_block(const get_raw_block_params& params, const fc::time_point& deadline) const;
// call from app() thread
std::unordered_map<account_name, std::optional<abi_serializer>>
get_block_serializers( const chain::signed_block_ptr& block, const fc::microseconds& max_time ) const;
Expand All @@ -338,6 +338,19 @@ class read_only {
std::unordered_map<account_name, std::optional<abi_serializer>> abi_cache,
const fc::microseconds& max_time ) const;

struct get_block_header_params {
string block_num_or_id;
bool include_extensions = false; // include block extensions (requires reading entire block off disk)
};

struct get_block_header_result {
chain::block_id_type id;
fc::variant signed_block_header;
std::optional<chain::extensions_type> block_extensions;
};

get_block_header_result get_block_header(const get_block_header_params& params, const fc::time_point& deadline) const;

struct get_block_info_params {
uint32_t block_num = 0;
};
Expand Down Expand Up @@ -782,7 +795,7 @@ class read_write {
// which is the format used by secondary index
uint8_t buffer[32];
memcpy(buffer, v.data(), 32);
fixed_bytes<32> fb(buffer);
fixed_bytes<32> fb(buffer);
return chain::key256_t(fb.get_array());
};
}
Expand All @@ -800,7 +813,7 @@ class read_write {
// which is the format used by secondary index
uint8_t buffer[20];
memcpy(buffer, v.data(), 20);
fixed_bytes<20> fb(buffer);
fixed_bytes<20> fb(buffer);
return chain::key256_t(fb.get_array());
};
}
Expand Down Expand Up @@ -895,9 +908,11 @@ FC_REFLECT(eosio::chain_apis::read_only::get_transaction_status_results, (state)
(head_timestamp)(irreversible_number)(irreversible_id)(irreversible_timestamp)(earliest_tracked_block_id)(earliest_tracked_block_number) )
FC_REFLECT(eosio::chain_apis::read_only::get_activated_protocol_features_params, (lower_bound)(upper_bound)(limit)(search_by_block_num)(reverse)(time_limit_ms) )
FC_REFLECT(eosio::chain_apis::read_only::get_activated_protocol_features_results, (activated_protocol_features)(more) )
FC_REFLECT(eosio::chain_apis::read_only::get_block_params, (block_num_or_id))
FC_REFLECT(eosio::chain_apis::read_only::get_raw_block_params, (block_num_or_id))
FC_REFLECT(eosio::chain_apis::read_only::get_block_info_params, (block_num))
FC_REFLECT(eosio::chain_apis::read_only::get_block_header_state_params, (block_num_or_id))
FC_REFLECT(eosio::chain_apis::read_only::get_block_header_params, (block_num_or_id)(include_extensions))
FC_REFLECT(eosio::chain_apis::read_only::get_block_header_result, (id)(signed_block_header)(block_extensions))

FC_REFLECT( eosio::chain_apis::read_write::push_transaction_results, (transaction_id)(processed) )
FC_REFLECT( eosio::chain_apis::read_write::send_transaction2_params, (return_failure_trace)(retry_trx)(retry_trx_num_blocks)(transaction) )
Expand Down
2 changes: 2 additions & 0 deletions programs/cleos/httpc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ namespace eosio { namespace client { namespace http {
const string compute_txn_func = chain_func_base + "/compute_transaction";
const string push_txns_func = chain_func_base + "/push_transactions";
const string get_block_func = chain_func_base + "/get_block";
const string get_raw_block_func = chain_func_base + "/get_raw_block";
const string get_block_header_func = chain_func_base + "/get_block_header";
const string get_block_info_func = chain_func_base + "/get_block_info";
const string get_block_header_state_func = chain_func_base + "/get_block_header_state";
const string get_account_func = chain_func_base + "/get_account";
Expand Down
45 changes: 32 additions & 13 deletions programs/cleos/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2768,6 +2768,15 @@ struct set_url_no_trailing_slash {
}
};

struct get_block_params {
string blockArg;
bool get_bhs = false;
bool get_binfo = false;
bool get_braw = false;
bool get_bheader = false;
bool get_bheader_extensions = false;
};

int main( int argc, char** argv ) {

fc::logger::get(DEFAULT_LOGGER).set_log_level(fc::log_level::debug);
Expand Down Expand Up @@ -3002,29 +3011,39 @@ int main( int argc, char** argv ) {
});

// get block
string blockArg;
bool get_bhs = false;
bool get_binfo = false;
get_block_params params;
auto getBlock = get->add_subcommand("block", localized("Retrieve a full block from the blockchain"));
getBlock->add_option("block", blockArg, localized("The number or ID of the block to retrieve"))->required();
getBlock->add_flag("--header-state", get_bhs, localized("Get block header state from fork database instead") );
getBlock->add_flag("--info", get_binfo, localized("Get block info from the blockchain by block num only") );
getBlock->callback([&blockArg, &get_bhs, &get_binfo] {
EOSC_ASSERT( !(get_bhs && get_binfo), "ERROR: Either --header-state or --info can be set" );
if (get_binfo) {
getBlock->add_option("block", params.blockArg, localized("The number or ID of the block to retrieve"))->required();
getBlock->add_flag("--header-state", params.get_bhs, localized("Get block header state from fork database instead") );
getBlock->add_flag("--info", params.get_binfo, localized("Get block info from the blockchain by block num only") );
getBlock->add_flag("--raw", params.get_braw, localized("Get raw block from the blockchain") );
getBlock->add_flag("--header", params.get_bheader, localized("Get block header from the blockchain") );
getBlock->add_flag("--header-with-extensions", params.get_bheader_extensions, localized("Get block header with block exntesions from the blockchain") );

getBlock->callback([&params] {
int num_flags = params.get_bhs + params.get_binfo + params.get_braw + params.get_bheader + params.get_bheader_extensions;
EOSC_ASSERT( num_flags <= 1, "ERROR: Only one of the following flags can be set: --header-state, --info, --raw, --header, --header-with-extensions." );
if (params.get_binfo) {
std::optional<int64_t> block_num;
try {
block_num = fc::to_int64(blockArg);
block_num = fc::to_int64(params.blockArg);
} catch (...) {
// error is handled in assertion below
}
EOSC_ASSERT( block_num.has_value() && (*block_num > 0), "Invalid block num: ${block_num}", ("block_num", blockArg) );
EOSC_ASSERT( block_num.has_value() && (*block_num > 0), "Invalid block num: ${block_num}", ("block_num", params.blockArg) );
const auto arg = fc::variant_object("block_num", static_cast<uint32_t>(*block_num));
std::cout << fc::json::to_pretty_string(call(get_block_info_func, arg)) << std::endl;
} else {
const auto arg = fc::variant_object("block_num_or_id", blockArg);
if (get_bhs) {
const auto arg = fc::variant_object("block_num_or_id", params.blockArg);
if (params.get_bhs) {
std::cout << fc::json::to_pretty_string(call(get_block_header_state_func, arg)) << std::endl;
} else if (params.get_braw) {
std::cout << fc::json::to_pretty_string(call(get_raw_block_func, arg)) << std::endl;
} else if (params.get_bheader || params.get_bheader_extensions) {
std::cout << fc::json::to_pretty_string(
call(get_block_header_func,
fc::mutable_variant_object("block_num_or_id", params.blockArg)
("include_extensions", params.get_bheader_extensions))) << std::endl;
} else {
std::cout << fc::json::to_pretty_string(call(get_block_func, arg)) << std::endl;
}
Expand Down
Loading

0 comments on commit 326c169

Please sign in to comment.