引言
区块链是由人类杰出科技成果组合而成的全新架构,对于生产关系的变革有巨大的潜力。数与科技团队致力于在实践中探索更加开放的加密经济基础设施,我们将逐步拆解主流区块链的底层技术细节,并且尝试将碎片化的区块链知识整理成树状知识图谱分享给社区,也欢迎有兴趣的朋友一起加入。
Cosmos是一套成熟且高可用区块链开发框架,拥有模块化设计、基于Golang开发、支持跨链协议等特点,是目前比较主流的区块链开发框架。通过Cosmos SDK,开发者可以快速构建出属于自己的区块链,高效地进行一系列个性化开发。
本文为Cosmos文档翻译系列第四篇,点击查看往期内容《剖析 Cosmos SDK 应用程序,Part 1:全节点与核心文件》
Modules
Modules 是SDK应用程序的灵魂。 它们可以被视为状态机中的状态机。 当交易通过ABCI从底层的Tendermint引擎中继到应用程序时,它由 baseapp 找到对应的模块以便进行处理。 这种范例使开发人员可以轻松构建复杂的状态机,因为他们所需的大多数模块通常已经存在。 对于开发人员而言,构建SDK应用程序所涉及的大部分工作都围绕构建其应用程序尚不存在的自定义模块,并将它们与已经存在的模块集成到一个统一的应用程序中。 在应用程序目录中,标准做法是将模块存储在x/文件夹中(不要与SDK的x/文件夹混淆,该文件夹包含已构建的模块)。
应用程序模块接口
模块必须实现Cosmos SDK AppModuleBasic中的interfaces 和 AppModule。 前者实现了模块的基本非依赖性元素,例如“编解码器”,而后者则处理了大部分模块方法(包括需要引用其他模块的keeper的方法)。AppModule和AppModuleBasic类型都在名为module.go的文件中定义。
AppModule在模块上公开了一组有用的方法,这些方法有助于将模块组合成一个一致的应用程序。 这些方法是从模块管理器中调用的,该模块管理应用程序的模块集合。
Message Types
每个module定义messages接口。 每个transaction包含一个或多个messages。
当全节点接收到有效的交易块时,Tendermint通过DeliverTx将每个交易发到应用程序 。 然后,应用程序处理事务:
收到交易后,应用程序首先从[] bytes反序列化得到。
然后,在提取交易中包含的消息之前,它会验证有关交易的一些信息,例如费用支付和签名
使用message的Type()方法,baseapp可以将其发到对应模块的 回调 handler以便对其进行处理。
如果消息已成功处理,则状态将更新。
模块开发人员在构建自己的模块时会创建自定义消息类型。 通常的做法是在消息的类型声明前加上Msg。 例如,消息类型MsgSend允许用户传输tokens:
它由bank模块的回调handler处理,最终会调用auth模块来写keeper以更新状态。
Handler
回调handler 是指模块的一部分,负责处理baseapp传递的message消息。 仅当通过ABCI接口的DeliverTx 消息从Tendermint 收到事务时,才执行模块的“处理程序”功能。 如果通过CheckTx,仅执行无状态检查和与费用相关的有状态检查。 为了更好地理解DeliverTx和CheckTx之间的区别以及有状态和无状态检查之间的区别,请看[这里](./ tx-lifecycle.md)。
模块的“处理程序”通常在名为handler.go的文件中定义,并包括:
NewHandler 将消息发到对应的回调“ handler”。 该函数返回一个“ handler”函数,此前这个函数在[AppModule`]中注册,以在应用程序的模块管理器中用于初始化应用程序的路由器。 接下来是nameservice tutorial的一个例子。
模块定义的每种消息类型的处理函数。 开发人员在这些函数中编写消息处理逻辑。 这通常包括进行状态检查以确保消息有效,并调用keeper的方法来更新状态。
处理程序函数返回结果类型为sdk.Result,该结果通知应用程序消息是否已成功处理:
Querier
Queriers与handlers非常相似,除了它们向状态查询用户而不是处理事务。 最终用户从interface 发起query,最终用户会提供queryRoute和一些data。 然后使用queryRoute通过baseapp的handleQueryCustom方法查询到正确的应用程序的querier 函数。
模块的Querier是在名为querier.go的文件中定义的,包括:
NewQuerier将查找到对应query函数。 此函数返回一个“querier”函数,此前它在 AppModule中注册,以在应用程序的模块管理器中用于初始化应用程序的查询路由器。
对于模块定义的每种需要查询的数据类型,都具有一个查询器功能。 开发人员在这些函数中编写查询处理逻辑。 这通常涉及调用[keeper] 的方法来查询状态并将其 序列化为JSON。
Keeper
Keepers是其模块存储器件。 要在模块的存储区中进行读取或写入,必须使用其keeper方法之一。 这是由Cosmos SDK的 object-capabilities 模型确保的。 只有持有商店密钥的对象才能访问它,只有模块的keeper才应持有该模块商店的密钥。
Keepers通常在名为keeper.go的文件中定义。 它包含keeper的类型定义和方法。
keeper类型定义通常包括:
多重存储中模块存储的“密钥”。
参考其他模块的keepers。 仅当keeper需要访问其他模块的存储(从它们读取或写入)时才需要。
对应用程序的“编解码器”的引用。 “ keeper”需要它在存储结构之前序列化处理,或在检索它们时将反序列化处理,因为存储仅接受“ [] bytes”作为值。
与类型定义一起,keeper.go文件的一个重要组成部分是Keeper的构造函数NewKeeper。 该函数实例化上面定义的类型的新keeper,并带有codec,存储keys以及可能引用其他模块的keeper作为参数。 从应用程序的构造函数中调用NewKeeper函数。 文件的其余部分定义了keeper的方法,主要是getter和setter。
命令行和 REST 接口
每个模块都定义了application-interfaces 向用户公开的命令行命令和REST routes。 用户可以创建模块中定义的类型的消息,或查询模块管理的状态的子集。
CLI
通常,与模块有关的命令在模块文件夹中名为client / cli的文件夹中定义。 CLI将命令分为交易和查询两类,分别在client / cli / tx.go和client / cli / query.go中定义。 这两个命令基于Cobra Library之上:
Transactions命令使用户可以生成新的事务,以便可以将它们包含在块中并更新状态。 应该为模块中定义的每个消息类型message-types创建一个命令。 该命令使用户提供的参数调用消息的构造函数,并将其包装到事务中。 SDK处理签名和其他事务元数据的添加。
用户可以查询模块定义的状态子集。 查询命令将查询转发到应用程序的查询路由器,然后将查询路由到提供的queryRoute参数的相应 querier。
REST
模块的REST接口允许用户生成事务并通过对应用程序的 light client daemon(LCD) 查询状态。 REST路由在client / rest / rest.go文件中定义,该文件包括:
RegisterRoutes函数,用于注册路由。 从主应用程序的接口 application-interfaces 中为应用程序内使用的每个模块调用此函数。 SDK中使用的路由器是 Gorilla's mux。
需要公开的每个查询或事务创建功能的自定义请求类型定义。 这些自定义请求类型基于Cosmos SDK的基本“请求”类型构建:
每个请求的一个处理函数可以找到给定的模块。 这些功能实现了服务请求所需的核心逻辑。
应用程序接口
Interfaces允许用户与全节点客户端进行交互。 这意味着从全节点查询数据,或者接受全节点中包含在块中的新事务。
通过汇总在应用程序使用的每个模块中定义的 CLI命令构建SDK应用程序的CLI。 应用程序的CLI通常具有后缀-cli(例如appcli),并在名为cmd / appcli / main.go的文件中定义。 该文件包含:
main()函数,用于构建appcli接口客户端。这个函数准备每个命令,并在构建它们之前将它们添加到rootCmd中。在appCli的根部,该函数添加了通用命令,例如status,keys和config,查询命令,tx命令和rest-server。
查询命令是通过调用queryCmd函数添加的,该函数也在appcli / main.go中定义。此函数返回一个Cobra命令,其中包含在每个应用程序模块中定义的查询命令(从main()函数作为sdk.ModuleClients数组传递),以及一些其他较低级别的查询命令,例如阻止或验证器查询。查询命令通过使用CLI的命令“ appcli query [query]”来调用。
通过调用txCmd函数来添加交易命令。与queryCmd类似,该函数返回一个Cobra命令,其中包含在每个应用程序模块中定义的tx命令,以及较低级别的tx命令,例如事务签名或广播。使用CLI的命令appcli tx [tx]调用Tx命令。
registerRoutes函数,在初始化 轻客户端(LCD)时从main()函数调用。 “ registerRoutes”调用应用程序每个模块的“ RegisterRoutes”功能,从而注册该模块routes 到LCD的查询路由。可以通过运行以下命令“ appcli rest-server”来启动LCD。
在nameservice demo中查看应用程序的主要命令行文件的示例。
Dependencies 和 Makefile
因为开发人员可以自由选择其依赖项管理器和项目构建方法。 也就是说,当前最常用的版本控制框架是go.mod。 它确保在整个应用程序中使用的每个库都以正确的版本导入。 请参阅demo中的示例:
为了构建应用程序,通常使用Makefile。 Makefile主要确保在构建应用程序的两个入口点appd和appcli之前运行go.mod。 请参阅 nameservice demo 中的Makefile示例。
原文链接:
https://docs.cosmos.network/master/basics/app-anatomy.html
作者:cosmos.network
你可能还喜欢:
关于我们:
杭州数与科技于2017年在中国杭州成立,由来自EOSIO、COSMOS等开源社区的核心开发者组成。我们致力于在实践中探索主流区块链底层技术,建设开放的信任经济基础设施、消除信任建立成本。
有疑问加站长微信联系(非本文作者)