开始编写你的程序

首先创建一个新的文件./app.go。这个文件是确定性状态机的核心。

app.go中,你定义了应用程序在接收交易时执行的操作。但首先,它要能够以正确的顺序接收交易。这是 Tendermint共识引擎的职责。

引入必要的依赖:

package app

import (
  "github.com/tendermint/tendermint/libs/log"
  "github.com/cosmos/cosmos-sdk/x/auth"

  bam "github.com/cosmos/cosmos-sdk/baseapp"
  dbm "github.com/tendermint/tendermint/libs/db"
)
1
2
3
4
5
6
7
8
9

下面是各引入模块和包的文档:

  • log: Tendermint 的日志
  • auth: Cosmos SDK 的auth模块
  • dbm: Tendermint 的数据库代码
  • baseapp: 如下

这里有几个包是tendermint包。Tendermint 通过名为 ABCI 的接口将交易从网络传递给应用程序。如果你要查看正在构建的区块链节点的架构,如下所示:

+---------------------+
|                     |
|     Application     |
|                     |
+--------+---+--------+
         ^   |
         |   | ABCI
         |   v
+--------+---+--------+
|                     |
|                     |
|     Tendermint      |
|                     |
|                     |
+---------------------+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

幸运的是,你不必实现ABCI接口。Cosmos SDK以baseapp的形式提供了它的实现样板。

baseapp做了以下几点:

  • 解码从 Tendermint 共识引擎接收到的交易。
  • 从交易中提取 messages 并做基本的合理性校验。
  • 将这些 message 路由到合适的模块使其被正确处理。注意baseapp并不了解你想要使用的具体模块。你要做的就是在app.go中声明这些模块,在接下来的教程中将会看到这些工作。baseapp仅实现了适用于任意模块的核心路由逻辑。
  • 如果 ABCI 消息是DeliverTxCheckTx)的话就Commit。
  • 帮助设置BeginBlockEndBlock,这两种消息让你能定义在每个区块开始和结束时执行的逻辑。实际上,每个模块实现了各自的BeginBlockEndBlock子逻辑,app的职责是它们都聚合起来。(注意:你不会在你的应用程序中使用这些消息)
  • 帮助初始化你的 state。
  • 帮助设置 queries。

现在你需要为应用程序创建一个新的自定义类型nameServiceApp。这个类型将嵌入baseapp(在Go中的嵌入类似于其他语言中的继承),这意味着它可以访问baseapp的所有方法。

const (
    appName = "nameservice"
)

type nameServiceApp struct {
    *bam.BaseApp
}
1
2
3
4
5
6
7

为你的应用添加一个简单的构造函数:

func NewNameServiceApp(logger log.Logger, db dbm.DB) *nameServiceApp {

    // First define the top level codec that will be shared by the different modules. Note: Codec will be explained later
    cdc := MakeCodec()

    // BaseApp handles interactions with Tendermint through the ABCI protocol
    bApp := bam.NewBaseApp(appName, logger, db, auth.DefaultTxDecoder(cdc))

    var app = &nameServiceApp{
        BaseApp: bApp,
        cdc:     cdc,
    }

    return app
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

很好!现在你有了应用程序的骨架;但是,仍然缺少具体功能。

baseapp不了解你要在应用程序中使用的路由或用户交互。应用程序的主要作用是定义这些路由。另一个作用是定义初始状态。这两件事都要求你向应用程序添加模块。

正如你在应用程序设计章节中看到的,你的nameservice需要三个模块:authbanknameservice。前两个已经存在了,但最后一个还没有!nameservice模块将定义你的状态机的大部分内容。下一步是构建它。

In order to complete your application, you need to include modules. Go ahead and start building your nameservice module. You will come back to app.go later.

为了完成应用程序,你需要引入一些模块。 继续开始构建你的域名服务模块 。 稍后会回到 app.go.