bitshares研究系列【bitshares-core api实现】

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 的帖子,期待您能留言交流!

H2
H3
H4
3 columns
2 columns
1 column
3 Comments