在区块链基础中,你已经了解到,区块链是一个通过共识由独立节点维护的、可复制且确定性的状态机。Cosmos SDK 通过清晰的关注点分离来实现这一模型:CometBFT 负责共识、网络和区块生产;ABCI(应用区块链接口,Application Blockchain Interface)定义了共识与应用之间的边界;Cosmos SDK 则实现应用逻辑和状态机。 本页将介绍 Cosmos SDK 区块链的高层架构:各个组件如何交互、每一层负责什么,以及这种分层为何重要。

Cosmos 应用架构

一个 Cosmos 区块链由 2 个不同的层组成:负责共识和区块生产的 CometBFT,以及包含应用逻辑、模块和交易执行逻辑的 Cosmos SDK 层。这两层之间是 ABCI(应用区块链接口,Application Blockchain Interface),它是连接二者的接口。
+---------------------------------------+
|                                       |
|       Cosmos SDK Application          |  <- State machine
|       (Modules, Keepers, State)       |     - Transaction execution
|                                       |     - Business logic
+------------------+--------------------+
                   |
                 ABCI  <- Application Blockchain Interface
                   |
+------------------+--------------------+
|                                       |
|              CometBFT                 |  <- Consensus engine
|      (Consensus, Networking,          |     - Block production
|         Block Replication)            |     - p2p networking
|                                       |
+---------------------------------------+
  • CometBFT:负责网络、区块生产和拜占庭容错共识的共识引擎。
  • ABCI:定义 CometBFT 何时以及如何调用应用的接口边界,强制分离共识与执行。在 Cosmos 应用中,ABCI 通过 BaseApp 实现。
  • Cosmos SDK:用于构建区块链应用(通常简称为“应用”)的框架。该应用是由可组合的模块组装而成的状态机。每个模块都拥有特定领域的逻辑、状态和交易;所有模块共同定义链的业务逻辑、执行交易,并生成加密状态承诺。这一层定义在 Cosmos 应用的 app.go 文件中。

分离共识与应用逻辑

将共识与应用逻辑分离带来了多项好处。安全性得到提升,因为隔离共识逻辑可以防止应用缺陷影响区块生产或网络稳定性。灵活性也随之增强,开发者无需重新实现共识,就能构建特定于应用的区块链。模块化设计使共识层和应用层能够独立演进,而可复用性则意味着同一个共识引擎(CometBFT)无需修改就能支撑许多不同的区块链。

节点与守护进程

区块链由节点组成,也就是区块链网络中的参与者。每个节点都会运行一个守护进程,其中既包含用于共识和网络的 CometBFT 实例,也包含用于状态机和执行逻辑的 Cosmos SDK 应用。该守护进程参与网络通信、与其他节点达成共识,并执行交易以更新应用状态。 节点可以承担不同角色。主要有两类节点:验证者和全节点:
  • 验证者是通过提议区块和对区块投票来参与共识的节点,其共识权重由质押或分配给它们的权力决定,因此它们负责区块生产。它们在投票前负责验证区块,确保只有有效区块才会被最终确认。
  • 全节点会复制并验证区块,但不参与共识投票;它们维护完整状态并响应查询,但不会对提案投票。
虽然通常任何人都可以运行全节点,但能否成为验证者取决于链的质押、治理或许可规则。在权益证明区块链中,验证者候选人根据其质押量被选出,并且必须满足特定条件才能当选验证者。在权威证明区块链中,验证者则根据许可条件进行选择。 要了解如何运行节点,请访问 Cosmos 节点教程。

CometBFT

CometBFT 是一个拜占庭容错共识引擎,提供快速且确定性的最终性。Cosmos SDK 区块链使用它在去中心化网络中复制状态机。

核心职责

CometBFT 负责多个核心职责:
  • 点对点网络:CometBFT 负责节点发现,建立并维护与其他验证者和全节点的连接,并实现 gossip 协议以在网络中传播信息。
  • 交易传播与内存池管理:当用户向某个节点提交交易时,CometBFT 会将其 gossip 给其他节点。每个节点都会维护一个内存池(mempool),这是一个用于存放尚未被打包进区块的有效交易的等待区。内存池会临时保存这些交易,直到某个验证者将其纳入区块提案。
  • 区块提案与交易排序:CometBFT 使用确定性的提议者选择机制来决定由哪个验证者提出下一个区块。提议者会从内存池中选择交易、确定顺序,并将它们打包为区块提案。
  • 拜占庭容错共识:CometBFT 协调投票轮次,由验证者对区块提案进行投票。当某个提案获得超过三分之二投票权的支持时,即达成共识,区块被最终确认。验证者会对自己的投票进行加密签名,以防止双重投票及其他恶意行为。
  • 区块复制:一旦区块被最终确认,CometBFT 会确保该区块复制到网络中的所有节点,从而维护所有已提交区块一致且有序的历史记录。
要进一步了解 CometbFT 的工作方式,请访问 CometBFT 文档。

拜占庭容错与最终性

拜占庭容错(BFT)指的是系统即使在部分参与者宕机、发送冲突消息或恶意行为时,仍然能够达成共识的能力。这个名称来自拜占庭将军问题。CometBFT 最多可容忍三分之一的投票权出现故障,同时仍能产生有效区块;只要超过三分之二的验证者在线,它就能维持活性。与工作量证明区块链不同,CometBFT 提供即时最终性:一旦区块被提交,就无法回滚。

编排区块生产

CometBFT 驱动整个区块生产生命周期。它决定何时生产区块(维持稳定的出块时间)、由哪个验证者提议每个区块(通过确定性的提议者选择),以及交易以何种顺序被纳入区块。CometBFT 通过管理验证者评估并投票区块提案的投票轮次,来协调整个共识过程。 要进一步了解 CometBFT 中共识的工作方式,请访问 CometBFT 文档。

内容无关性

CometBFT 不关心区块内容,也不关心应用如何实现。它将交易视为不透明的字节数组,只确保所有节点接收到相同且有序的序列,而不会解释这些数据的含义。所有特定于应用的逻辑都位于 SDK 层,该层使用 Protocol Buffers 将结构化消息序列化为 CometBFT 可以承载的字节。

ABCI(应用区块链接口)

ABCI 是 CometBFT 与 Cosmos SDK 区块链应用之间一种严格的请求/响应接口。它定义了区块执行生命周期,并确保共识与应用逻辑之间的清晰分离,从而保证安全、可靠的区块生产,不会因应用故障或缺陷而被破坏。 ABCI 是单向的:所有调用都从 CometBFT 流向应用,应用不能调用或控制 CometBFT。Cosmos SDK 应用必须对所有 ABCI 调用作出确定性响应,也就是在给定相同输入时产生相同结果。 ABCI 本身是一个无状态协议,不包含任何业务逻辑。它仅提供 CometBFT 共识引擎与 Cosmos SDK 应用之间的接口定义:前者负责区块生产,后者定义业务逻辑和状态机。

区块生命周期方法

作为区块生产的驱动方,CometBFT 控制何时调用 Cosmos SDK 应用程序。它会在区块生产过程中的特定阶段通过 ABCI 调用应用程序:为 mempool 验证交易(CheckTx)、构造或评估区块提案(PrepareProposal 和 ProcessProposal)、执行最终确认的区块(FinalizeBlock),以及持久化状态(Commit)。SDK 应用程序会对这些调用作出响应,但不能主动发起它们。这意味着,决定区块生产与状态转换时机和节奏的是 CometBFT,而不是 SDK 应用程序。这个 ABCI 边界也阻止了应用逻辑影响共识过程。
+---------------+              |          +--------------------------+
|   CometBFT    |              |          |    SDK Application       |
| (Consensus)   |             ABCI        |  (State Machine Logic)   |
+---------------+              |          +--------------------------+
1) CheckTx                     |
   Mempool validation ---------|-------> Validate tx (sigs, fees)
                               |
2) PrepareProposal             |
   Proposer builds block ------|--------> Construct block proposal
                               |
3) ProcessProposal             |
   Validators evaluate --------|--------> Validate proposal
                               |
4) Consensus                   |
   BFT voting, finalizing block|
   (SDK not involved)          |
                               |
5) FinalizeBlock               |
   Execute block --------------|--------> PreBlock hooks
                               |          BeginBlock hooks
                               |          Execute transactions
                               |          EndBlock hooks
                               |          Return AppHash
6) Commit                      |
   Persist state --------------|--------> Persist to disk
                               |<-------- Return AppHash
  1. CheckTx 在交易被加入 mempool 之前执行验证。它会检查交易格式是否正确,以及在经济上是否可行(签名正确、手续费充足),但不会修改状态。这可以保护 mempool 免受垃圾交易攻击。
  2. PrepareProposal 会在验证者构造新区块提案时被调用。这让应用程序能够有限地参与区块构造,例如重排交易顺序或加入应用特定的数据。
  3. ProcessProposal 会在验证者评估其他验证者提交的区块提案时被调用。应用程序可以在投票接受提案之前,按照应用特定规则验证该提案区块。
  4. Consensus 完全发生在 CometBFT 内部。在验证者通过 ProcessProposal 对提案完成评估后,他们会参与 BFT 投票轮次。如果提案获得超过三分之二投票权的支持,就达成共识,区块被最终确认。
  5. FinalizeBlock 会在某个区块达成共识后被调用。状态转换就在这里发生,整个区块会以原子方式执行。BaseApp 会按以下顺序调用生命周期钩子:PreBlock hooks、BeginBlock hooks、交易执行,以及 EndBlock hooks。应用程序会返回新的 AppHash(对状态的密码学承诺)以及任何验证者集合变更。
  6. Commit 会在 FinalizeBlock 之后被调用,用于将最终确认的状态持久化到节点本地磁盘,并返回会写入下一个区块头的 AppHash。
PreBlock hooks 在 SDK v0.50 中引入,会在 BeginBlock 之前运行。PreBlockers 必须通过 SetOrderPreBlockers 显式排序。某些核心模块(尤其是 x/auth)依赖 PreBlock 执行;如果缺少 PreBlock 的接线配置,将导致运行时错误。
CometBFT 决定区块何时产生以及交易以什么顺序出现,Cosmos SDK 决定这些交易是否有效以及它们如何改变状态,而 ABCI 则定义了两者之间的接口。 若想更深入了解 ABCI,请访问 ABCI 页面。

Cosmos SDK 应用程序

Cosmos SDK 应用程序是一个确定性的状态机,用于定义区块链的行为。它专注于定义区块链跟踪哪些状态、哪些交易是有效的,以及交易如何改变状态。应用程序使用 Protocol Buffers 定义交易和消息格式以进行序列化,通过检查签名和手续费来验证交易,执行消息处理器以应用状态转换,维护所有模块的状态,并生成对当前状态进行密码学承诺的 AppHash。

应用程序结构

一个典型的 Cosmos SDK 应用程序由以下部分组成:
  • BaseApp:样板代码,提供 ABCI 实现和执行框架,使链能够与 CometBFT 交互。
  • 模块:领域特定逻辑的构建块,例如交易、自定义业务逻辑,以及治理/权限控制。
  • 状态 Multistore:按模块隔离的键值存储集合,用于保存应用程序状态。
  • Keepers:提供访问模块状态的接口,同时强制执行访问控制。
  • app.go:作为组合根,将所有部分连接在一起。
若想完整了解 Cosmos SDK 的整体结构,请访问 SDK 结构简介

BaseApp 与 app.go

BaseApp 是 Cosmos SDK 对 ABCI 接口的标准实现。它处理来自 CometBFT 的所有 ABCI 方法调用,将消息路由到适当的模块处理器,管理状态版本与缓存,并强制执行交易执行语义。 开发者不会直接实现 ABCI;相反,他们会扩展 BaseApp,并向其中注册自己的模块、处理器和执行逻辑。 要进一步了解 BaseApp,请访问 BaseApp 页面。 app.go 文件是 Cosmos SDK 应用程序的组合根。这里负责组装具体的区块链:创建 BaseApp 实例、实例化所有模块 keeper 及其依赖、为各模块状态注册 store key、接线模块的生命周期钩子,并配置交易处理流程。 要进一步了解 app.go,请访问 app.go 页面。 模块还会定义 genesis 状态初始化和迁移逻辑,以支持链升级,使应用状态能够随着时间安全演进。

模块、交易与应用逻辑

模块是 Cosmos SDK 应用程序的构建块。每个模块都实现一个特定功能领域:bank 模块处理代币转账,staking 模块管理验证者委托,governance 模块实现链上提案,等等。每个模块都像一个独立的小型状态机,会按照自己的规则处理交易并更新状态。整个应用程序中的所有模块共同构成一个统一且完整的状态机。 模块通过消息处理器提供其业务逻辑。消息类似函数调用,用于指定某个操作(例如“向地址 X 发送 100 个代币”)及其带类型的参数。用户通过提交包含这些消息的交易来调用模块逻辑。在执行期间,每条消息都会被路由到对应模块的处理器,由它运行业务逻辑并更新状态。 在 Cosmos SDK 中,transaction 是一个经过签名和序列化的容器,封装一个或多个 messages。message 表示实际要执行的操作(例如“发送代币”或“委托质押”),而 transaction 则附加签名、手续费和 gas 上限等元数据。区块中包含的是 transaction;在区块执行期间(FinalizeBlock),每笔 transaction 中的 message 都会被提取出来,并路由到相应模块的处理器执行。transaction 中包含其创建者的签名,用于授权所请求的状态变更。 模块使用 Protocol Buffers (Protobuf) 定义消息类型,以提供类型安全、跨语言的序列化能力。由于 CometBFT 将交易视为原始字节,而 KV stores 也只接受字节数组,因此 Protobuf 会将结构化消息和状态数据序列化为字节,以便传输和存储。模块还会定义状态 schema(模块存储哪些数据)、状态转换(消息如何修改状态)、查询(允许客户端读取模块状态),以及可选的生命周期钩子,用于在区块边界执行任务。 要进一步了解交易和消息,请访问 Transactions 页面。若想更深入了解模块,请访问 模块简介页面,或查看 模块教程 以学习如何从零开始构建一个模块。

区块生命周期钩子

除了处理单笔交易之外,模块还可以定义在区块执行特定阶段运行的生命周期钩子。这些钩子使模块能够在区块边界执行任务,例如铸造奖励、更新验证者集合,或在交易执行前准备状态。 在 FinalizeBlock 期间,BaseApp 会按以下顺序调用模块钩子:
  1. PreBlock - 在区块执行开始前准备状态
  2. BeginBlock - 在区块开始时执行任务(例如铸造奖励)
  3. Transaction execution - 对每笔交易:运行 AnteHandler,执行消息处理器,运行 PostHandler(如果已配置)
  4. EndBlock - 在区块结束时执行任务(例如更新验证者集合)
模块由 ModuleManager 统一协调,它会编排这些生命周期事件,以及 genesis 初始化和模块升级。

状态

在 Cosmos SDK 应用程序中,状态以 multistore 中的一组键值对形式保存。 状态变更发生在区块执行期间。在某个区块通过共识最终确认之后,CometBFT 会通过 ABCI 调用 FinalizeBlock,并按顺序在 Cosmos SDK 应用程序中执行该区块内的每笔交易。对于每笔交易,其中的消息会被提取出来,并路由到对应模块的 MsgServer。MsgServer 负责验证消息,而 keepers 则执行模块的业务逻辑并更新状态。 在执行完区块中的交易并更新状态后,每个节点都会根据自己的本地状态计算 AppHash。AppHash 是该区块结束时应用程序状态的密码学证明,并会被写入下一个区块头。这确保了状态更新只有在达成共识后才会生效。按照设计,Cosmos SDK 应用程序中的所有状态变更都是确定性且可重放的:针对相同初始状态执行同一个区块,始终会产生相同的最终状态。

Keepers

Keeper 是模块状态的守门人。它们提供访问和修改模块状态的唯一接口,负责在模块之间实施访问控制,并封装状态访问逻辑。这与对象能力模型一致:模块只能访问在初始化期间显式传递给它们的能力(其他 keeper)。模块之间通过 keeper 接口交互,而不是直接访问彼此的状态,这强化了模块化并防止紧耦合。要进一步了解 keeper,请访问模块简介页面。

KV 存储与 Multistore

Cosmos SDK 应用的状态存储在 multistore 中,它是多个键值存储的集合。每个模块都拥有一个带命名空间的键值存储,将其数据与其他模块隔离开来。multistore 将所有模块存储组合成一个统一的状态表示,并基于高度进行版本管理,以支持历史查询。 KV 存储只接受字节数组([]byte)作为值,因此任何自定义数据结构在存储之前都必须使用 codec 进行编组。这样可以确保整个应用中的序列化方式保持一致,通常使用 Protocol Buffers。
+-----------------------------------------+
|           Multistore (Root)             |
|                                         |
|  +----------+  +----------+  +-----+    |
|  |  Bank    |  | Staking  |  | ... |    |
|  |  Store   |  |  Store   |  |     |    |
|  +----------+  +----------+  +-----+    |
|                                         |
+-----------------------------------------+
要了解更多,请访问 Store 页面。

Merkle 树与承诺

应用状态通过 Merkle 树进行提交。每个模块存储都组织为一棵 Merkle 树(实现为 IAVL 树),而 multistore 的根则是由各模块存储根组成的一棵树。AppHash 是这个 multistore 结构的根哈希,用于唯一标识某个状态版本。
                 AppHash (Root)
                      |
        +-------------+-------------+
        |                           |
    BankRoot                   StakingRoot
        |                           |
   +----+----+                 +----+----+
   |         |                 |         |
 Key1     Key2               Key3      Key4
CometBFT 会将 AppHash 包含在区块头中,使任何人都可以验证状态承诺。这对轻客户端至关重要,因为它们无需下载所有区块即可验证状态。 访问 Store 页面 以进一步了解 Cosmos 如何使用 IAVL 树。

状态如何在节点之间复制

上述状态变更会在网络中的每个节点上独立发生。CometBFT 不会直接复制应用状态,而是复制区块(有序交易)和共识决策。随后,每个节点都会通过本地的 Cosmos SDK 应用独立执行这些区块。 这种设计完全依赖确定性执行。当所有节点执行相同的有序交易时,确定性执行保证它们会得到完全相同的状态。节点通过比较 AppHash 承诺来验证这一一致性。如果执行不是确定性的,节点就会计算出不同的 AppHash,共识也将失败。 在执行完一个区块后,每个节点都会根据本地状态计算 AppHash。这个 AppHash 会被包含在下一个区块头中。验证者会对包含该 AppHash 的区块头进行加密签名,以证明它们执行了该区块并得到了这一状态。状态发生分歧的节点会生成不同的 AppHash,而验证者不会为包含错误承诺的区块签名。这使得状态不一致可以被检测出来,并确保共识意味着所有诚实节点之间的状态一致。 为了保持确定性,应用应避免一些常见陷阱:使用区块时间而不是本地时间戳(后者在各节点之间会不同),使用整数运算而不是浮点运算(后者可能因硬件不同而产生差异),使用以区块数据为种子的确定性随机数,并将所有必要数据都包含在交易中,而不是调用外部 API。

通信层

Cosmos SDK 区块链会根据上下文使用不同的通信机制。
  • 节点到节点通信:节点之间通过 CometBFT 的自定义点对点 gossip 协议进行通信。这负责处理交易在网络中的传播、区块向所有节点的复制,以及投票和提案等共识消息。这部分通信完全发生在 CometBFT 内部,与应用无关。
  • 共识到应用的通信:CometBFT 通过 ABCI 使用本地函数调用与 Cosmos SDK 应用通信。这是在同一个守护进程内的进程内通信,而不是网络协议。CometBFT 会在区块生命周期的关键节点调用应用,而应用则返回执行结果和状态承诺。
  • 客户端到节点通信:客户端(钱包、浏览器和其他外部应用)通过 Cosmos SDK 的 gRPC API 与节点交互,并可通过 gRPC-Gateway 使用 HTTP/REST。这个外部 API 允许客户端查询应用状态并提交交易以进入 mempool。此通信与共识完全分离,客户端绝不会直接与 CometBFT 的共识协议交互。
要了解更多,请访问CLI、gRPC 与 REST API 页面。

总结

Cosmos SDK 区块链的架构清晰地分离了三个关注点。CometBFT 通过其共识机制决定区块何时产生以及其中包含哪些交易。ABCI 定义应用如何以及在何时作为区块生命周期的一部分被调用。Cosmos SDK 定义这些交易的含义,以及它们如何以确定性的方式改变状态。

下一步

  • Transaction Lifecycle 页面会追踪一笔交易从提交开始,经过 mempool 准入、共识到执行的整个过程。
  • Application Anatomy 页面会深入讲解如何构建一个 Cosmos SDK 应用,详细介绍模块、keeper 以及 app.go 的组合方式。

In Blockchain Basics, you learned that a blockchain is a replicated, deterministic state machine maintained by independent nodes through consensus. The Cosmos SDK implements this model through a clean separation of concerns: CometBFT handles consensus, networking, and block production; ABCI (Application Blockchain Interface) defines the boundary between consensus and application; and the Cosmos SDK implements the application logic and state machine. This page explains the high-level architecture of Cosmos SDK blockchains: how components interact, what each layer is responsible for, and why this separation matters.

Cosmos Application Architecture

A Cosmos blockchain consists of 2 distinct layers: CometBFT for consensus and block production, and the Cosmos SDK layer which contains the application logic, modules, and transaction execution logic. Between these layers is the ABCI (Application Blockchain Interface), which is the interface that connects them.
+---------------------------------------+
|                                       |
|       Cosmos SDK Application          |  <- State machine
|       (Modules, Keepers, State)       |     - Transaction execution
|                                       |     - Business logic
+------------------+--------------------+
                   |
                 ABCI  <- Application Blockchain Interface
                   |
+------------------+--------------------+
|                                       |
|              CometBFT                 |  <- Consensus engine
|      (Consensus, Networking,          |     - Block production
|         Block Replication)            |     - p2p networking
|                                       |
+---------------------------------------+
  • CometBFT: the consensus engine that handles networking, block production, and Byzantine Fault Tolerant consensus.
  • ABCI: the interface boundary that defines when and how CometBFT invokes the application, enforcing separation between consensus and execution. The ABCI is implemented in a Cosmos application via BaseApp.
  • Cosmos SDK: the framework for building the blockchain application (often simply called “the application”), which is a state machine assembled from composable modules. Each module owns a specific domain of logic, state, and transactions; together, modules define the chain’s business logic, execute transactions, and produce cryptographic state commitments. This layer is defined in the app.go file of a Cosmos application.

Separating Consensus and Application Logic

Separating consensus from application logic provides several benefits. Security improves because isolating consensus logic prevents application bugs from affecting block production or network stability. Flexibility increases as developers can build application-specific blockchains without reimplementing consensus. The modular design allows consensus and application layers to evolve independently, and reusability means one consensus engine (CometBFT) can power many different blockchains without modification.

Nodes and Daemons

A blockchain is made up of nodes, or participants in the blockchain network. Each node runs a daemon process that includes both a CometBFT instance for consensus and networking, and a Cosmos SDK application for the state machine and execution logic. The daemon participates in networking, reaches consensus with other nodes, and executes transactions to update the application state. Nodes can operate in different roles. There are two main types of nodes, validators and full nodes:
  • Validators are nodes that participate in consensus by proposing and voting on blocks, with consensus power staked or attributed to them making them responsible for block production. They are in charge of validating blocks before voting, ensuring that only valid blocks are finalized.
  • Full nodes replicate and verify blocks without participating in consensus voting, maintaining complete state and answering queries but not voting on proposals.
Although anyone can typically run a full node, becoming a validator depends on the chain’s staking, governance, or permissioning rules. In a proof-of-stake blockchain, validator candidates are selected based on their stake, and they must meet certain criteria to be elected as validators. In a proof-of-authority blockchain, validators are selected based on permissioned criteria. To learn how to run a node, visit the Cosmos Node Tutorial.

CometBFT

CometBFT is a Byzantine Fault Tolerant consensus engine that provides fast, deterministic finality. It’s used by Cosmos SDK blockchains to replicate the state machine across a decentralized network.

Core Responsibilities

CometBFT handles several core responsibilities:
  • Peer-to-peer networking: CometBFT manages node discovery, establishes and maintains connections with other validators and full nodes, and implements gossip protocols for propagating information across the network.
  • Transaction propagation and mempool management: When users submit transactions to a node, CometBFT gossips them to other nodes. Each node maintains a mempool (memory pool), which is a waiting area for valid transactions that have not yet been included in a block. The mempool holds transactions temporarily until a validator includes them in a block proposal.
  • Block proposal and transaction ordering: CometBFT uses deterministic proposer selection to choose which validator will propose the next block. The proposer selects transactions from the mempool, orders them, and packages them into a block proposal.
  • Byzantine Fault Tolerant consensus: CometBFT coordinates voting rounds where validators vote on block proposals. When a proposal receives votes from more than two-thirds of voting power, consensus is reached and the block is finalized. Validators cryptographically sign their votes, ensuring against double-voting and other forms of malicious behavior.
  • Block replication: Once finalized, CometBFT ensures the block is replicated across all nodes in the network, maintaining a consistent, ordered history of all committed blocks.
To learn more about how CometbFT works, visit the CometBFT Documentation.

Byzantine Fault Tolerance and Finality

Byzantine Fault Tolerance (BFT) is a system’s ability to reach consensus even when some participants crash, send conflicting messages, or act maliciously. The name comes from the Byzantine Generals Problem. CometBFT tolerates up to one-third of voting power being faulty while still producing valid blocks, and maintains liveness as long as more than two-thirds of validators are online. Unlike proof-of-work blockchains, CometBFT provides instant finality: once a block is committed, it cannot be reverted.

Orchestrating Block Production

CometBFT drives the entire block production lifecycle. It determines when blocks are produced (maintaining consistent block times), which validator proposes each block (through deterministic proposer selection), and the order in which transactions are included in blocks. CometBFT coordinates the consensus process by managing the voting rounds where validators evaluate and vote on block proposals. To learn more about how consensus in CometBFT works, visit the CometBFT Documentation.

Content Agnosticism

CometBFT is agnostic to block content and application implementation. It treats transactions as opaque byte arrays, ensuring all nodes receive the same ordered sequence without interpreting what they mean. All application-specific logic lives in the SDK layer, which uses Protocol Buffers to serialize structured messages into bytes CometBFT can carry.

ABCI (Application Blockchain Interface)

ABCI is a strict request/response interface between CometBFT and a Cosmos SDK blockchain application. It defines the block execution lifecycle and ensures a clean separation between consensus and application logic to ensure secure, reliable block production that cannot be compromised by application faults or bugs. The ABCI is unidirectional: all calls flow from CometBFT to the application, and the application cannot call into or control CometBFT. The Cosmos SDK application must respond deterministically to all ABCI calls, producing the same results given the same inputs. The ABCI itself is a stateless protocol containing no business logic. It only provides the interface definitions between the CometBFT consensus engine, which handles block production, and the Cosmos SDK application, which defines the business logic and state machine.

Block Lifecycle Methods

As the driver of block production, CometBFT controls when the Cosmos SDK application is invoked. It calls the application through ABCI at specific points during block production to validate transactions for the mempool (CheckTx), to construct or evaluate block proposals (PrepareProposal and ProcessProposal), to execute finalized blocks (FinalizeBlock), and to persist state (Commit). The SDK application responds to these calls but cannot initiate them. This means CometBFT, not the SDK application, determines the timing and cadence of block production and state transitions. This ABCI boundary also prevents application logic from influencing consensus.
+---------------+              |          +--------------------------+
|   CometBFT    |              |          |    SDK Application       |
| (Consensus)   |             ABCI        |  (State Machine Logic)   |
+---------------+              |          +--------------------------+
1) CheckTx                     |
   Mempool validation ---------|-------> Validate tx (sigs, fees)
                               |
2) PrepareProposal             |
   Proposer builds block ------|--------> Construct block proposal
                               |
3) ProcessProposal             |
   Validators evaluate --------|--------> Validate proposal
                               |
4) Consensus                   |
   BFT voting, finalizing block|
   (SDK not involved)          |
                               |
5) FinalizeBlock               |
   Execute block --------------|--------> PreBlock hooks
                               |          BeginBlock hooks
                               |          Execute transactions
                               |          EndBlock hooks
                               |          Return AppHash
6) Commit                      |
   Persist state --------------|--------> Persist to disk
                               |<-------- Return AppHash
  1. CheckTx validates transactions before adding them to the mempool. It checks that transactions are well-formed and economically viable (proper signature, sufficient fees) without making state changes. This protects the mempool against spam.
  2. PrepareProposal is invoked when a validator constructs a new block proposal. This gives the application limited control over block construction, allowing it to reorder transactions or add application-specific data.
  3. ProcessProposal is called when validators evaluate a block proposal from another validator. The application can validate the proposed block according to application-specific rules before voting to accept it.
  4. Consensus occurs entirely within CometBFT. After validators evaluate the proposal (via ProcessProposal), they participate in BFT voting rounds. If the proposal receives votes from more than two-thirds of voting power, consensus is reached and the block is finalized.
  5. FinalizeBlock is invoked after consensus on a block is reached. This is where state transitions occur, executing the entire block atomically. BaseApp invokes lifecycle hooks in this order: PreBlock hooks, BeginBlock hooks, transaction execution, and EndBlock hooks. The application returns the new AppHash (a cryptographic commitment to the state) and any validator set changes.
  6. Commit is called after FinalizeBlock to persist the finalized state to the nodes’ local disk and return the AppHash that gets included in the next block header.
PreBlock hooks were introduced in SDK v0.50, which run before BeginBlock. PreBlockers must be explicitly ordered using SetOrderPreBlockers. Some core modules (notably x/auth) require PreBlock execution; missing PreBlock wiring will cause runtime errors.
CometBFT decides when blocks happen and what order transactions appear in, the Cosmos SDK decides whether those transactions are valid and how they change state, and the ABCI defines the interface between the two. For a more in-depth look at the ABCI, visit the ABCI page.

Cosmos SDK Application

A Cosmos SDK application is a deterministic state machine that defines a blockchain’s behavior. It focuses entirely on defining what state the blockchain tracks, what transactions are valid, and how transactions change state. The applications defines transaction and message formats using Protocol Buffers for serialization, validates transactions by checking signatures and fees, executes message handlers to apply state transitions, maintains state across all modules, and produces the AppHash that cryptographically commits to the current state.

Application Structure

A typical Cosmos SDK application consists of:
  • BaseApp: boilerplate code that provides the ABCI implementation and execution framework for a chain to interact with CometBFT.
  • Modules: building blocks of domain-specific logic such as transactions, custom business logic, and governance/permissioning.
  • State Multistore: a collection of key-value stores that store the state of the application, isolated by module.
  • Keepers: providing interfaces for accessing module state while enforcing access control.
  • app.go: serving as the composition root that wires everything together.
For a complete overview of Cosmos SDK structure, visit the Intro to SDK Structure

BaseApp and app.go

BaseApp is the Cosmos SDK’s standard implementation of the ABCI interface. It handles all ABCI method calls from CometBFT, routes messages to the appropriate module handlers, manages state versioning and caching, and enforces transaction execution semantics. Developers do not implement ABCI directly; instead, they extend BaseApp and register their modules, handlers, and execution logic with it. To learn more about BaseApp, visit the BaseApp page. The app.go file is the composition root of a Cosmos SDK application. This is where a specific blockchain is assembled by creating the BaseApp instance, instantiating all module keepers with their dependencies, registering store keys for each module’s state, wiring module lifecycle hooks, and configuring transaction processing. To learn more about app.go, visit the app.go page. Modules also define genesis state initialization and migration logic to support chain upgrades, allowing application state to evolve safely over time.

Modules, Transactions, and Application Logic

Modules are the building blocks of Cosmos SDK applications. Each module implements a specific domain of functionality: the bank module handles token transfers, the staking module manages validator delegation, the governance module implements on-chain proposals, and so on. Every module acts as its own mini state machine, processing transactions and updating state according to its own rules. Together, modules for the entire application form a single, cohesive state machine. A module provides its business logic through message handlers. Messages work like function calls that specify an operation (like “send 100 tokens to address X”) with typed parameters. Users invoke module logic by submitting transactions that contain these messages. During execution, each message gets routed to its module’s handler, which runs the business logic and updates state. In the Cosmos SDK, a transaction is a signed, serialized container that wraps one or more messages. Messages represent the actual operations to execute (like “send tokens” or “delegate stake”), while the transaction adds metadata like signatures, fees, and gas limit. Blocks contain transactions, and during block execution (FinalizeBlock), each transaction’s messages are extracted and routed to the appropriate module handlers for execution. Transactions contain signatures from their creators authorizing the requested state change. Modules define message types using Protocol Buffers (Protobuf), which provide type-safe, cross-language serialization. Since CometBFT treats transactions as raw bytes and KV stores only accept byte arrays, Protobuf serializes structured messages and state data into bytes for transmission and storage. Modules also define state schemas (what data the module stores), state transitions (how messages modify state), queries (allowing clients to read module state), and optional lifecycle hooks for tasks that run at block boundaries. To learn more about the transactions and messages, visit the Transactions page. For more in-depth information on modules, visit the Intro to Modules page or check out the Module Tutorial to learn how to build a module from scratch.

Block Lifecycle Hooks

Beyond processing individual transactions, modules can define lifecycle hooks that run at specific points during block execution. These hooks allow modules to perform tasks at block boundaries, such as minting rewards, updating validator sets, or preparing state before transactions execute. During FinalizeBlock, BaseApp invokes module hooks in this sequence:
  1. PreBlock - Prepare state before block execution begins
  2. BeginBlock - Perform tasks at block start (e.g., minting rewards)
  3. Transaction execution - For each transaction: run AnteHandler, execute message handlers, run PostHandler (if configured)
  4. EndBlock - Perform tasks at block end (e.g., updating validator sets)
Modules are coordinated by a ModuleManager, which orchestrates these lifecycle events along with genesis initialization and module upgrades.

State

In a Cosmos SDK application, state is stored as a collection of key-value pairs in a multistore. State changes occur during block execution. After consensus finalizes a block, FinalizeBlock is invoked by CometBFT via the ABCI, which executes each transaction in the Cosmos SDK application in order. For each transaction, the messages are extracted and routed to the MsgServer of the corresponding module. The MsgServer validates messages, and the keepers executes the business logic of the module and updates the state. After executing the transactions in the block and updating state, each node computes the AppHash from its local state. The AppHash is a cryptographic proof of the state of the application at the end of the block, and is included in the next block header. This ensures that state updates only take effect once consensus is reached. By design, all state changes in a Cosmos SDK application are deterministic and replayable: executing the same block against the same initial state will always produce the same final state.

Keepers

Keepers are the gatekeepers to module state. They provide the only interface for accessing and mutating a module’s state, enforce access control between modules, and encapsulate state access logic. This aligns with the object capability model, where modules can only access capabilities (other keepers) explicitly passed to them during initialization. Modules interact through keeper interfaces rather than directly accessing each other’s state, enforcing modularity and preventing tight coupling. To learn more about keepers, visit the Intro to Modules page.

KV Stores and Multistore

The state of a Cosmos SDK application is stored in a multistore, which is a collection of key-value stores. Each module owns a namespaced key-value store, isolating its data from other modules. The multistore combines all module stores into a single, unified state representation with height-based versioning for historical queries. KV stores only accept byte arrays ([]byte) as values, so any custom data structures must be marshaled using a codec before being stored. This ensures consistent serialization across the application, typically using Protocol Buffers.
+-----------------------------------------+
|           Multistore (Root)             |
|                                         |
|  +----------+  +----------+  +-----+    |
|  |  Bank    |  | Staking  |  | ... |    |
|  |  Store   |  |  Store   |  |     |    |
|  +----------+  +----------+  +-----+    |
|                                         |
+-----------------------------------------+
To learn more, visit the Store page.

Merkle Trees and Commitments

Application state is committed using Merkle trees. Each module store is organized as a Merkle tree (implemented as an IAVL tree), and the multistore root is a tree of module store roots. The AppHash is the root hash of this multistore structure, uniquely identifying a state version.
                 AppHash (Root)
                      |
        +-------------+-------------+
        |                           |
    BankRoot                   StakingRoot
        |                           |
   +----+----+                 +----+----+
   |         |                 |         |
 Key1     Key2               Key3      Key4
CometBFT includes the AppHash in block headers, allowing anyone to verify state commitments. This is crucial for light clients, which can verify state without downloading all blocks. Visit the Store page to learn more about how Cosmos uses IAVL trees.

How State Replicates Across Nodes

The state changes described above happen independently on every node in the network. CometBFT does not replicate application state directly—instead, it replicates blocks (ordered transactions) and consensus decisions. Each node then independently executes these blocks through its local Cosmos SDK application. This design relies entirely on deterministic execution. When all nodes execute the same ordered transactions, deterministic execution guarantees they arrive at identical state. Nodes verify this agreement by comparing AppHash commitments. If execution were non-deterministic, nodes would compute different AppHashes and consensus would fail. After executing a block, each node computes the AppHash from its local state. This AppHash is included in the next block header. Validators cryptographically sign block headers that include the AppHash, attesting that they executed the block and arrived at that state. Nodes with divergent state produce different AppHashes, and validators will not sign blocks with incorrect commitments. This makes state disagreement detectable and ensures that consensus implies state agreement across all honest nodes. To maintain determinism, applications should avoid common pitfalls: use block time instead of local timestamps (which vary across nodes), use integer math instead of floating-point arithmetic (which can differ by hardware), use deterministic randomness seeded with block data, and include all necessary data in transactions rather than making external API calls.

Communication Layers

Cosmos SDK blockchains use different communication mechanisms depending on the context.
  • Node-to-Node Communication: Nodes communicate with each other using CometBFT’s custom peer-to-peer gossip protocol. This handles transaction propagation across the network, block replication to all nodes, and consensus messages like votes and proposals. This communication is entirely within CometBFT and is application-agnostic.
  • Consensus to Application Communication: CometBFT communicates with the Cosmos SDK application through ABCI using local function calls. This is in-process communication within the same daemon, not a network protocol. CometBFT invokes the application at key points in the block lifecycle, and the application returns execution results and state commitments.
  • Client to Node Communication: Clients (wallets, explorers, and other external applications) interact with nodes through the Cosmos SDK’s gRPC API, with HTTP/REST available via gRPC-Gateway. This external API allows clients to query application state and submit transactions for mempool inclusion. This communication is completely separate from consensus—clients never directly interact with CometBFT’s consensus protocols.
To learn more, visit the CLI, gRPC, and REST API page.

Summary

The architecture of a Cosmos SDK blockchain cleanly separates three concerns. CometBFT determines when blocks happen and which transactions they contain through its consensus mechanism. ABCI defines how and when the application is invoked as part of the block lifecycle. The Cosmos SDK defines what those transactions mean and how they change state deterministically.

What’s Next

  • The Transaction Lifecycle page follows a transaction from submission through mempool admission, consensus, and execution.
  • The Application Anatomy page provides a deep dive into building a Cosmos SDK application, exploring modules, keepers, and the composition of app.go in detail.