bitshares研究系列【bitshares-ui代码分析之api】
bitshares研究系列【bitshares-ui代码分析之api调用流程】
这两篇文章主要是对bitshares-ui做api做了分析,这次来看看bitshares-core的api实现。
想了解bitshares节点更多细节的,可以去 @cifer那了解,他的分析很到位!
节点rpc消息处理
/libraries/app/application.cpp
new_connection()中创建websocket_api_connection实例
/libraries/fc/src/rpc/websocket_api.cpp
websocket消息接收后,会处理到on_message函数中:
std::string on_message(
const std::string& message,
bool send_message = true );
on_message函数中对接收消息处理后,调用:
auto result = _rpc_state.local_call( call.method, call.params );
也会返回结果:
if( call.id )
{
auto reply = fc::json::to_string( response( *call.id, result, "2.0" ), fc::json::stringify_large_ints_and_doubles, _max_conversion_depth );
if( send_message )
_connection.send_message( reply );
return reply;
}
再对照rpc格式看一下:
> {"method": "call", "params": [1, "login", ["", ""]], "id": 2}
< {"id":2,"jsonrpc":"2.0","result":true}
/libraries/fc/src/rpc/state.cpp
variant state::local_call( const string& method_name, const variants& args )
local_call函数会根据method_name,找到对应的方法,这个对应关系通过add_method()添加到_methods map中,在websocket_api_connection中注册了"call"、"notice"、"callback"这几个方法。
/libraries/fc/include/fc/rpc/api_connection.hpp
variant receive_call( api_id_type api_id, const string& method_name, const variants& args = variants() )const
{
FC_ASSERT( _local_apis.size() > api_id );
return _local_apis[api_id]->call( method_name, args );
}
在这里根据传进来的API_ID,调用不同库(如database、network等)的call方法,而这个map是通过register_api注册的。
类generic_api中做了api调用的处理,转来转去,不仔细去看了!
api调用实现
/libraries/app/api.cpp database_api.cpp
api的真正实现在这两个文件中。
看一个api的实现:get_objects
fc::variants database_api::get_objects(const vector<object_id_type>& ids)const
{
return my->get_objects( ids );
}
fc::variants database_api_impl::get_objects(const vector<object_id_type>& ids)const
{
if( _subscribe_callback ) {
for( auto id : ids )
{
if( id.type() == operation_history_object_type && id.space() == protocol_ids ) continue;
if( id.type() == impl_account_transaction_history_object_type && id.space() == implementation_ids ) continue;
this->subscribe_to_item( id );
}
}
fc::variants result;
result.reserve(ids.size());
std::transform(ids.begin(), ids.end(), std::back_inserter(result),
[this](object_id_type id) -> fc::variant {
if(auto obj = _db.find_object(id))
return obj->to_variant();
return {};
});
return result;
}
再看看api:get_block
optional<signed_block> database_api::get_block(uint32_t block_num)const
{
return my->get_block( block_num );
}
optional<signed_block> database_api_impl::get_block(uint32_t block_num)const
{
return _db.fetch_block_by_number(block_num);
}
都调用了_db对象,db的定义如下:
graphene::chain::database& _db;
libraries/chain/include/graphene/chain/database.hpp
类database的定义,基本上是bitshares的对象数据和交易数据的最上层管理者。
bitshares研究系列【bitshares-ui代码分析之api】
bitshares研究系列【bitshares-ui代码分析之api调用流程】
加上本文 bitshares-core api的实现,api的就简单分析这些了,有需要再做处理。
感谢您阅读 @chaimyu 的帖子,期待您能留言交流!