本文共 2463 字,大约阅读时间需要 8 分钟。
substrates 节点的启动流程主要涉及命令行参数解析、服务配置和节点运行。以下将详细介绍从命令行启动到节点运行的关键步骤。
substrates 节点启动的主要入口位于 substrate/node/main.rs,通过调用 cli::run 函数开始。该函数继承自 node/cli/src/lib.rs,其核心逻辑包含以下几个方面:
clap库解析命令行参数,生成核心参数对象。命令行参数的具体解析由 core/cli/src/lib.rs 中的 parse_and_prepare 函数完成。该函数定义了多种常见的节点运行模式,例如运行模式、构建配置、导出块等,并根据不同参数组合返回对应的配置指令。例如:
substrates 节点的核心功能由 service 组件实现,包含以下关键模块:
服务的工厂类(Factory)通过宏 construct_service_factory 定义不同的服务类型:
#[macro_exportmacro_rules! construct_service_factory { ( FullService = $full_service:ty { $( $full_service_init:tt )* }, AuthoritySetup = { $( $authority_setup:tt )* }, LightService = $light_service:ty { $( $light_service_init:tt )* } ) => ( fn new_light(config: $crate::FactoryFullConfiguration ) -> $crate::Result { ($( $light_service_init )* )(config) } fn new_full(config: $crate::FactoryFullConfiguration ) -> Result { let service = ($( $full_service_init )* )(config).and_then(|service| { ($( $authority_setup )*)(service) }); service } ... )] 该宏定义了创建全节点或轻节点的工厂函数,分别初始化对应服务。
服务的运行基于 substrates-service 库,使用 tokio 实现异步编程:
use tokio::executor::Executor;#[derive(Debug, Clone)]struct Service { pub client: Client, pub network: Network, pub network_status_sinks: Vecrecv , ...}impl Service { pub async fn run ( &self, event_loop: T, ) -> result { // 其余实现细节 }} 服务初始化后,会创建网络协议、交易池等基础设施,并监听网络事件。
根据节点的角色(全节点或轻节点),调用不同的服务工厂进行初始化:
let config = create_run_node_config(self.params.left.clone(), spec_factory, self.impl_name, self.version)?;let service = service.run(config)?;run_service(exit, self.params.left, self.params.right, config) .map_err(Into::into)
运行服务闭包内部完成以下步骤:
substrates节点基于 tokio 异步执行框架,使用 futureAndHandle 执行服务。代码片段如下:
runtime.executor().spawn(exit.until(informant).map(|_| ()));
该代码绑定事件循环,定期轮询事件处理,确保服务能够响应网络消息和交易请求。
substrates 节点启动流程主要包含命令行参数解析、服务工厂初始化和异步运行。通过清晰的配置管理和高效的运行机制,确保节点能够稳定运行并高效处理网络任务。
转载地址:http://zmahz.baihongyu.com/