A Technical Introduction to Cosmos SDK
Architectural Design Overview
The Cosmos SDK is a npm-like framework that allows developers to easily build complex, secure and application-agnostic state-machines on top of Tendermint. Applications built with the Cosmos SDK are essentially multi-asset, interoperable public chains based on BPoS (Bonded Proof-of-Stake).
Below is a infographic of how transactions are handled by an application built with Cosmos SDK when replayed from Tendermint via ABCI, orDeliverTx
to be specific:
Application Anatomy
A Cosmos SDK application generally consists of the following major components:
I. Full-Node Client
A full-node client is a binary (or daemon) built and run by participants in the Cosmos network to instantiate their own state-machine, and connect to other full-nodes. A full-node fully validates transactions and blocks of a blockchain.
II. Core Application
The core of a Cosmos SDK application mainly consists of Type Definition and Constructor Functions
Type Definition
Defined in app.go
the type definition of a custom application is merely a struct comprised of the following:
- Reference to
baseapp
: A reference to thebaseapp
defines a customapp
type embeddingbaseapp
for your application. In other words, the reference tobaseapp
allows the custom application to inherit most ofbaseapp
's core logic such as ABCI methods and routing logic. - List of Store Keys: Each module in the Cosmos SDK uses multistore to persist their part of the state. Access to such stores requires a list of keys that are declared in the type definition of the
app
. - List of Each Module’s
Keeper
s:keeper
is an abstract piece in each module to handle the module's interaction with stores, specify references to other modules'keeper
s, and implement other core functionalities of the module. For cross-module interactions to work all modules in the Cosmos SDK need to have theirkeeper
s declared in theapp
's type definition and exported as interfaces to other modules so that thekeeper
's methods of one module can be called and accessed in other modules when authorized. - Reference to
codec
: Defaulted to go-amino, thecodec
in your Cosmos SDK application can be substituted with other suitable encoding frameworks as long as they persist data stores in byte slices and are deterministic. - Reference to Module Manager: Self-explanatory. A reference to an object containing a list of the applications modules, a.k.a the Module Manager.
Example of application type definition
Constructor Function
As the name would suggest, a constructor function creates an instance of the app
with the application's type definition declared in it. Specifically constructor functions perform the following actions when called:
- Initialize a new
app
instance with a reference to acodec
, a reference tobaseapp
, and a list of store keys - Initialize each module’s
keeper
s as defined in Type Definition in correct order (i.e. moduleJay
'skeeper
s need to be instantiated before moduleKen
's if moduleKen
'skeeper
s require a reference to moduleJay
's) - Initialize the
app
's Module Manager - an object where
- A reference to each module is passed in (assuming the modules initialized here are intended to be modified later)
routes
(to a module'shandler
) andquery routes
(to a module'squerier
) are initialized- Invariants (i.e. variables evaluated at the end of each block) of each module are registered. Each invariant’s value needs to be equal to a pre-defined value specified in its corresponding module
- Order of execution between key functions (e.g.
InitGenesis
,BeginBlocker
,EndBlocker
) of each module is set. - Remainers of
app
's parameters are set - Stores are mounted
- An
app
instance is returned
Example of application constructor
III. Modules
With many of key modules needed for a coherent application already built into the Cosmos SDK developers can easily build complex state-machines by integrating custom modules with the existing ones. Currently the SDK supports the following modules:
In the rest of this section, we will briefly explore two of the most fundamental building blocks of a module — Interfaces and Message Types.
Interfaces
By definition a Cosmos SDK module implements two interfaces: AppModuleBasic
and AppModule
. AppModule
typically contains a module's inter-module dependent methods while the non-dependent ones (e.g. codec
) going into AppModuleBasic
.
Message Types
Each module that implements the message
interface needs to define its own custom message types. Such message types shall also be seen as "messages to be included in transactions". After receiving a block of transactions relayed from Tendermint through DeliverTx
, the application needs to go through a 4-step procedure before committing state changes:
- Unmarshal each transaction from byte slices or
[]bytes
- Perform sanity checks (e.g. fees, signatures) and extract the message(s) contained in the transaction
- Route the message(s) to the appropriate module’s
handler
- Process the message(s)
IV. Application Interfaces
Each Cosmos SDK application implements a Command-Line Interface (CLI) that is used to interact with full-node clients. Out of the box the CLI supports the following generic commands:
V. Dependencies and Makefile
The Cosmos SDK gives the developers the freedom to choose their preferred dependency manager and project building method. Go Modules is commonly used for the former and Makefile for the latter.
Remarks
Whether you are new to blockchain or not, learning a new codebase can be a bit daunting at first. This piece was my attempt to give developers looking to build on the Cosmos SDK a glance into the framework, and to hopefully help ease up their code break-in period. If you are ready to get your hands dirty with building your own application-specific blockchains, check out the tutorial here. Last but not least, thank you for checking out!
Resources
[1] GitHub. (2019). cosmos/cosmos-sdk. [online] Available at: https://github.com/cosmos/cosmos-sdk/tree/master/docs [Accessed 11 Nov. 2019].