Cosmos Application Architecture
The most basic Cosmos SDK blockchain application consists of three distinct layers, all running within a node’s daemon process:- CometBFT: the consensus engine that handles networking, block production, and Byzantine Fault Tolerant consensus.
- ABCI: the strict interface boundary that defines when and how CometBFT invokes the application, enforcing separation between consensus and execution.
- Cosmos SDK: the framework for building the blockchain application (often simply called “the application”), which is the state machine that defines the business logic, executes transactions, maintains state across modules, and produces cryptographic state commitments.
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.
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.
Byzantine Fault Tolerance and Finality
Byzantine Fault Tolerance (BFT) refers to a system’s ability to reach consensus even when some participants behave arbitrarily; they may crash, send conflicting messages, or act maliciously. The name comes from the Byzantine Generals Problem, a game theory thought experiment about coordinating agreement in the presence of malicious or faulty participants. In blockchain networks, Byzantine faults include validators that are compromised, malicious, or simply behaving unpredictably due to software bugs or network issues. CometBFT’s BFT consensus was built for strong security and finality. As long as fewer than one-third of voting power is Byzantine (malicious or faulty), the network will not commit conflicting blocks. This means the network can tolerate up to 33% of validators acting arbitrarily without breaking consensus. Liveness is maintained as long as more than two-thirds of voting power is online and participating, ensuring the network continues producing blocks. Unlike proof-of-work blockchains, CometBFT provides instant finality: once a block is committed, it cannot be reverted. There are no reorganizations or probabilistic finality when building a blockchain using CometBFT.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
Although CometBFT fascilitates the production of blocks, it is agnostic to both the content of the blocks and the implementation of the application. It treats transactions as opaque byte arrays, and it does not interpret or validate their contents beyond basic formatting. CometBFT has no knowledge of what constitutes a valid transaction for your application; it only ensures that all nodes receive the same ordered sequence of transaction bytes. This is why the Cosmos SDK uses Protocol Buffers to serialize structured transaction messages into the byte format that CometBFT expects. All application-specific logic is handled by the Cosmos SDK application layer through the ABCI interface. This generalization also extends to programming languages. Because the ABCI is a language-agnostic protocol, applications can be written in any language that implements the ABCI interface. While the Cosmos SDK is written in Go, applications have been built using ABCI implementations in Rust, Python, JavaScript, and other languages. CometBFT doesn’t care what language your application uses—it only cares that the application responds correctly to ABCI method calls.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.- 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.
- 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.
- 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.
- 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.
- 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.
- 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.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.
runtime.AppBuilder, which reduces boilerplate and provides clear dependency graphs. Modern SDK chains typically use Governance v1, where proposals are submitted via MsgSubmitProposal containing executable messages.
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.
Modules also define genesis state initialization and migration logic to support chain upgrades, allowing application state to evolve safely over time.
To learn more about app.go, visit the app.go page.
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. Transaction validation and preprocessing are handled by an AnteHandler, which runs before message execution to verify signatures, deduct fees, and enforce transaction validity rules. The AnteHandler executes for each transaction individually during the transaction execution phase. If it rejects a transaction (due to invalid signature, insufficient fees, etc.), the message handlers never run for that transaction. An optional PostHandler may run after message execution to perform additional checks or bookkeeping. To learn more about the transactions and messages, visit the Transactions page. For more in-depth information on creating modules, visit the Build a module section.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:- PreBlock - Prepare state before block execution begins
- BeginBlock - Perform tasks at block start (e.g., minting rewards)
- Transaction execution - For each transaction: run AnteHandler, execute message handlers, run PostHandler (if configured)
- EndBlock - Perform tasks at block end (e.g., updating validator sets)
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 their module handlers, which are functions that validate messages, execute the business logic of the module, and update state using keepers.
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 Keepers 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.
Merkle Trees and Commitments
Application state is committed using Merkle tree structures. Each module store is organized as a Merkle tree, and the multistore root is a Merkle tree of module store roots. The AppHash is the root hash of this multistore structure, uniquely identifying a state version.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 must 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.