Tendermint源码分析——启动流程分析

准备参数

cli参数:

node --proxy_app=dummy --home "C:\Users\Administrator\datadir\tendermint"

Tendermint的cli解析使用cobra库!

flags vs args

让我们将程序定格在(c *Command) ExecuteC【/vendor/github.com/spf13/cobra/command.go#】中的下面这一行:

err=cmd.execute(flags)

变量图
我们可以看出,从命令行传进来的所有“命令”都算作参数,而标记是“- -”开头的参数。换句话说,标记是去掉不带“- -”开头的参数!

梦开始的地方

代码位置:/vendor/github.com/spf13/cobra/command.go#(c *Command) execute

if c.RunE != nil {
    if err := c.RunE(c, argWoFlags); err != nil {
        return err
    }
} else {
    c.Run(c, argWoFlags) 
}

c.RunE(c, argWoFlags)是引发node启动服务的根。一切有意思的事情从这里开始。c.RunE(c, argWoFlags)是调用匿名函数RunE,而RunE的赋值则是在NewRunNodeCmd函数(/cmd/tendermints/commands/run_node.go):

// NewRunNodeCmd returns the command that allows the CLI to start a
// node. It can be used with a custom PrivValidator and in-process ABCI application.
func NewRunNodeCmd(nodeProvider nm.NodeProvider) *cobra.Command {
    cmd := &cobra.Command{
        Use:   "node",
        Short: "Run the tendermint node",
        RunE: func(cmd *cobra.Command, args []string) error {   //匿名函数
            // Create & start node
            n, err := nodeProvider(config, logger)
            if err != nil {
                return fmt.Errorf("Failed to create node: %v", err)
            }

        if err := n.Start(); err != nil {
            return fmt.Errorf("Failed to start node: %v", err)
        } else {
            logger.Info("Started node", "nodeInfo", n.Switch().NodeInfo())  //节点启动完毕打印日志Started node
        }

        // Trap signal, run forever.
        n.RunForever()

        return nil
    },
}

    AddNodeFlags(cmd)
    return cmd
}

这个匿名函数有三个功能:

1、创建node(nodeProvider(config, logger))
2、启动node(n.Start())
3、监听停止node的信号(n.RunForever())

下面我们一个功能往下走!我么先看创建node!

创建node

nodeProvider(config,logger)具体执行DefaultNewNode函数(/node/node.go#DefaultNewNode)。DefaultNewNode函数会返回一个Node全局变量。

// DefaultNewNode returns a Tendermint node with default settings for the
// PrivValidator, ClientCreator, GenesisDoc, and DBProvider.
// It implements NodeProvider.
func DefaultNewNode(config *cfg.Config, logger log.Logger) (*Node, error) {
    return NewNode(config,
        types.LoadOrGenPrivValidatorFS(config.PrivValidatorFile()),
        proxy.DefaultClientCreator(config.ProxyApp, config.ABCI, config.DBDir()),
        DefaultGenesisDocProviderFunc(config),
        DefaultDBProvider,
        logger)
}

DefaultNewNode的第一个实参为config。config的定义在/cmd/tendermint/commands/root.go:

var (
    config = cfg.DefaultConfig()
)

注意:用户在命令行传入的参数,那只是启动节点所需的非常小的一部分参数。大多数参数都是需要从默认配置中加载的。config全局变量加载了node所需的所有默认参数(主要是默认基础配置、默认RPC配置、默认P2P配置、内存池配置、共识配置和交易索引配置)。

DefaultNewNode的第二个实参为types.LoadOrGenPrivValidatorFS(config.PrivValidatorFile()),该函数会返回一个PrivValidatorFS实例。

DefaultNewNode的第三个实参为proxy.DefaultClientCreator(config.ProxyApp,config.ABCI,config.DBDir()),其中DefaultClientCreator函数(/proxy/client.go#DefaultClientCreator)的第一个实参config.ProxyApp=“dummy”;
第二个实参config.ABCI=“socket”;第三个实参config.DBDir()
=“C:\Users\Administrator\datadir\tendermint\data”。

但是具体负责创建这个全局变量的函数走的是NewNode函数。代码在/node/node.go#NewNode。

// NewNode returns a new, ready to go, Tendermint Node.
func NewNode(config *cfg.Config,
    privValida
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值