正如《EOS源码学习系列》提到EOS项目大体上是按program
/plugin
/libraries
/contracts
四大块来组织代码,本篇先从最顶层的应用程序作为入口来了解EOS的框架。
节点程序:eosd
eosd
是运行在节点上的deamon服务程序,主要用途有:
- 生产区块:打包、验证交易生成区块。
- 提供REST API:提供API查询区块账户等信息,提供钱包功能,如管理key、交易签名等。EOS提供了
eosc
命令行工具来调用api。 - 本地开发。
最简单的启动方式就是不带参数启动
$ ./eosd
如果是本地开发环境可以添加--skip-transaction-signatures
来跳过key签名。
$ ./eosd --skip-transaction-signatures
eosd源码
eosd的源代码路径是programs/eosd/main.cpp
。
include区
从include区可以看到,eosd程序大量采用了各种plugin插件。
/* app应用框架,用来注册框架和执行初始化、启动等动作 */
#include <appbase/application.hpp>
/* 引入全部插件 */
#include <eos/producer_plugin/producer_plugin.hpp>
#include <eos/chain_plugin/chain_plugin.hpp>
#include <eos/http_plugin/http_plugin.hpp>
#include <eos/chain_api_plugin/chain_api_plugin.hpp>
#include <eos/db_plugin/db_plugin.hpp>
#include <eos/net_plugin/net_plugin.hpp>
#include <eos/account_history_plugin/account_history_plugin.hpp>
#include <eos/account_history_api_plugin/account_history_api_plugin.hpp>
#include <eos/wallet_api_plugin/wallet_api_plugin.hpp>
#include <eos/net_api_plugin/net_api_plugin.hpp>
#include <eosio/txn_test_gen_plugin/txn_test_gen_plugin.hpp>
#include <eosio/faucet_testnet_plugin/faucet_testnet_plugin.hpp>
/* 通用函数 */
#include <fc/log/logger_config.hpp>
#include <fc/log/appender.hpp>
#include <fc/exception/exception.hpp>
/* boost */
#include <boost/exception/diagnostic_information.hpp>
#include "config.hpp"
主程序流程
eosd
的main函数看起来比较简单:
- 通过
app()
函数获得一个application单例; - 单例注册各种plugin
app().register_plugin<plugin_name>()
; - 单例初始化,并且初始化的时候指定了三个必要的plugin,分别是
chain_plugin
,http_plugin
,net_plugin
,分别对应区块链服务、REST API服务和与外部其他节点通信的网络服务。 - 单例启动,触发使能的plugin启动,
app().start()
- 单例主线程while循环,等待退出信号,
app().exec()
代码如下:
int main(int argc, char** argv)
{
try {
app().set_version(eosio::eosd::config::version);
app().register_plugin<net_api_plugin>();
app().register_plugin<chain_api_plugin>();
app().register_plugin<wallet_api_plugin>();
app().register_plugin<producer_plugin>();
app().register_plugin<account_history_api_plugin>();
app().register_plugin<db_plugin>();
app().register_plugin<txn_test_gen_plugin>();
app().register_plugin<faucet_testnet_plugin>();
if(!app().initialize<chain_plugin, http_plugin, net_plugin>(argc, argv))
return -1;
initialize_logging();
ilog("eosd version ${ver}", ("ver", eosio::eosd::config::itoh(static_cast<uint32_t>(app().version()))));
app().startup();
app().exec();
} catch (const fc::exception& e) {
elog("${e}", ("e",e.to_detail_string()));
} catch (const boost::exception& e) {
elog("${e}", ("e",boost::diagnostic_information(e)));
} catch (const std::exception& e) {
elog("${e}", ("e",e.what()));
} catch (...) {
elog("unknown exception");
}
return 0;
}
小结
eosd
程序由一个app
框架实例加载众多功能插件plugin
实现其功能,其中必要的三个插件为chain_plugin
, http_plugin
, net_plugin
。eosd
程序本身是一个简单跑app实例的架子,关注插件的注册加载启动,节点服务的实际功能均由插件实现,后续文章再深入分析。
下一篇,将从命令行客户端工具eosc
的角度,了解eosd
实际提供了什么样的api。