What is BaseApp?
BaseApp is the foundational component that implements the Application Blockchain Interface (ABCI) and manages the core application logic. Every Cosmos SDK application embeds BaseApp to handle consensus interactions, transaction routing, and state management.
// Location: baseapp/baseapp.go:86
type BaseApp struct {
// initialized on creation
mu sync . Mutex
logger log . Logger
name string // application name
db dbm . DB // database backend
cms storetypes . CommitMultiStore // Main (uncached) state
qms storetypes . MultiStore // Query-only multistore
storeLoader StoreLoader // store loading function
grpcQueryRouter * GRPCQueryRouter // gRPC query routing
msgServiceRouter * MsgServiceRouter // message routing
interfaceRegistry codectypes . InterfaceRegistry
txDecoder sdk . TxDecoder // decode tx bytes
txEncoder sdk . TxEncoder // encode tx to bytes
mempool mempool . Mempool // transaction mempool
anteHandler sdk . AnteHandler // pre-execution checks
postHandler sdk . PostHandler // post-execution logic
abciHandlers sdk . ABCIHandlers // lifecycle handlers
stateManager * state . Manager // state management
snapshotManager * snapshots . Manager // state snapshots
// ... more fields
}
Creating a BaseApp
// Location: baseapp/baseapp.go:195
func NewBaseApp (
name string ,
logger log . Logger ,
db dbm . DB ,
txDecoder sdk . TxDecoder ,
options ... func ( * BaseApp ),
) * BaseApp
Example Initialization
import (
" cosmossdk.io/log "
" github.com/cosmos/cosmos-sdk/baseapp "
dbm " github.com/cosmos/cosmos-db "
)
// Create a new application
app := baseapp . NewBaseApp (
"myapp" ,
logger ,
db ,
txDecoder ,
baseapp . SetPruning ( pruningOpts ),
baseapp . SetMinGasPrices ( "0.001stake" ),
baseapp . SetChainID ( "mychain-1" ),
)
Core Components
State Management
BaseApp manages multiple state layers:
// Location: baseapp/state/state.go:13
type State struct {
MultiStore storetypes . CacheMultiStore
mtx sync . RWMutex
ctx sdk . Context
span trace . Span
}
The root store containing all module substores. Committed state that persists between blocks. cms storetypes . CommitMultiStore
Manages different execution contexts (CheckTx, FinalizeBlock) with isolated state branches. stateManager * state . Manager
Optional write-through cache for state that persists between blocks. interBlockCache storetypes . MultiStorePersistentCache
Message Routing
BaseApp routes messages to the appropriate module handlers:
// Location: baseapp/msg_service_router.go
type MsgServiceRouter struct {
routes sync . Map // msg type -> handler
hybridHandlers map [ string ] Handler // hybrid handlers
}
type MessageRouter interface {
RegisterService ( sd * grpc . ServiceDesc , handler interface {})
SetInterfaceRegistry ( interfaceRegistry codectypes . InterfaceRegistry )
Handler ( msg sdk . Msg ) Handler
HandlerByTypeURL ( typeURL string ) Handler
}
Messages are routed by their type URL (e.g., /cosmos.bank.v1beta1.MsgSend).
Query Routing
// Location: baseapp/grpcrouter.go:5562
type GRPCQueryRouter struct {
routes map [ string ] GRPCQueryHandler
interfaceRegistry codectypes . InterfaceRegistry
serviceData [] serviceData
}
Handles gRPC queries from clients, routing them to registered query services.
ABCI Lifecycle
InitChain
Called once when the blockchain starts:
// Location: baseapp/abci.go:53
func ( app * BaseApp ) InitChain ( req * abci . RequestInitChain ) ( * abci . ResponseInitChain , error ) {
// Validate chain ID
if req . ChainId != app . chainID {
return nil , fmt . Errorf ( "invalid chain-id" )
}
// Set initial height
app . initialHeight = req . InitialHeight
if app . initialHeight == 0 {
app . initialHeight = 1
}
// Initialize state
app . stateManager . SetState ( execModeFinalize , app . cms , initHeader , ... )
// Store consensus params
if req . ConsensusParams != nil {
err := app . StoreConsensusParams ( finalizeState . Context (), * req . ConsensusParams )
}
// Call InitChain handler
if app . abciHandlers . InitChainer != nil {
res , err := app . abciHandlers . InitChainer ( finalizeState . Context (), req )
}
return & abci . ResponseInitChain { ... }, nil
}
FinalizeBlock
Executes transactions and finalizes a block:
PreBlock
Runs module PreBlockers (e.g., for vote extensions processing)
BeginBlock
Executes module BeginBlockers in order
DeliverTx
Executes each transaction in the block:
Run ante handler
Route and execute messages
Run post handler
Emit events
EndBlock
Executes module EndBlockers (e.g., validator updates)
Commit
Writes state changes and computes app hash
// Simplified FinalizeBlock flow
func ( app * BaseApp ) FinalizeBlock ( req * abci . RequestFinalizeBlock ) ( * abci . ResponseFinalizeBlock , error ) {
// Get finalize state
finalizeState := app . stateManager . GetState ( execModeFinalize )
// PreBlock
if app . abciHandlers . PreBlocker != nil {
ctx , err := app . abciHandlers . PreBlocker ( ctx )
}
// BeginBlock
if app . abciHandlers . BeginBlocker != nil {
err := app . abciHandlers . BeginBlocker ( ctx )
}
// Execute transactions
for _ , tx := range req . Txs {
res := app . runTx ( ctx , tx , execModeFinalize )
txResults = append ( txResults , res )
}
// EndBlock
if app . abciHandlers . EndBlocker != nil {
err := app . abciHandlers . EndBlocker ( ctx )
}
return & abci . ResponseFinalizeBlock {
TxResults : txResults ,
AppHash : appHash ,
}, nil
}
Commit
func ( app * BaseApp ) Commit () ( * abci . ResponseCommit , error ) {
// Write pending state
finalizeState . MultiStore . Write ()
// Commit to disk
commitID := app . cms . Commit ()
return & abci . ResponseCommit {
RetainHeight : retainHeight ,
}, nil
}
Transaction Execution
CheckTx Mode
Validates transactions before mempool inclusion:
func ( app * BaseApp ) CheckTx ( req * abci . RequestCheckTx ) ( * abci . ResponseCheckTx , error ) {
// Decode transaction
tx , err := app . txDecoder ( req . Tx )
// Run in check mode
gInfo , result , _ , err := app . runTx ( ctx , tx , execModeCheck )
return & abci . ResponseCheckTx {
GasWanted : gInfo . GasWanted ,
GasUsed : gInfo . GasUsed ,
Priority : result . Priority ,
}, nil
}
runTx Method
Core transaction execution logic:
func ( app * BaseApp ) runTx (
ctx sdk . Context ,
tx sdk . Tx ,
mode execMode ,
) ( gInfo sdk . GasInfo , result * sdk . Result , anteEvents [] abci . Event , err error ) {
// 1. Ante Handler
newCtx , err := app . anteHandler ( ctx , tx , mode == execModeSimulate )
// 2. Execute Messages
msgResponses , err := app . runMsgs ( newCtx , msgs , mode )
// 3. Post Handler
if app . postHandler != nil {
newCtx , err = app . postHandler ( newCtx , tx , mode == execModeSimulate , err == nil )
}
return gInfo , result , anteEvents , err
}
Configuration Options
BaseApp supports extensive configuration:
// Location: baseapp/options.go
// Set pruning options
func SetPruning ( opts pruningtypes . PruningOptions ) func ( * BaseApp )
// Set minimum gas prices
func SetMinGasPrices ( gasPricesStr string ) func ( * BaseApp )
// Set mempool
func SetMempool ( mempool mempool . Mempool ) func ( * BaseApp )
// Set ante handler
func SetAnteHandler ( ah sdk . AnteHandler ) func ( * BaseApp )
// Set snapshot store
func SetSnapshotStore ( ss * snapshots . Store ) func ( * BaseApp )
Example Configuration
app := baseapp . NewBaseApp (
appName ,
logger ,
db ,
txConfig . TxDecoder (),
baseapp . SetPruning ( pruningtypes . NewPruningOptionsFromString ( "everything" )),
baseapp . SetMinGasPrices ( "0.001stake" ),
baseapp . SetChainID ( chainID ),
baseapp . SetMempool ( mempool . NewPriorityMempool ()),
baseapp . SetAnteHandler ( anteHandler ),
baseapp . SetStreamingManager ( streamingManager ),
)
Gas Management
// Transaction gas meter
gasMeter := storetypes . NewGasMeter ( gasLimit )
// Block gas meter (tracks total gas per block)
blockGasMeter := storetypes . NewInfiniteGasMeter ()
BaseApp can disable block gas metering with disableBlockGasMeter for parallel execution scenarios. Validators must validate total gas in ProcessProposal.
Snapshot Management
BaseApp integrates state sync snapshots:
snapshotManager * snapshots . Manager
// Create snapshot
func ( app * BaseApp ) Snapshot ( height uint64 ) error
// Restore from snapshot
func ( app * BaseApp ) OfferSnapshot ( snapshot * abci . Snapshot ) error
Optimistic Execution
Experimental feature for parallel block execution:
optimisticExec * oe . OptimisticExecution
Executes the next block optimistically while consensus finalizes the current block.
Key Interfaces
// Store loader customizes store initialization
type StoreLoader func ( ms storetypes . CommitMultiStore ) error
// Param store for consensus parameters
type ParamStore interface {
Get ( ctx sdk . Context ) ( cmtproto . ConsensusParams , error )
Has ( ctx sdk . Context ) ( bool , error )
Set ( ctx sdk . Context , cp cmtproto . ConsensusParams ) error
}
// Circuit breaker for emergency stops
type CircuitBreaker interface {
IsAllowed ( ctx context . Context , typeURL string ) ( bool , error )
}
Best Practices
Always Use BaseApp Options
Configure BaseApp through option functions rather than direct field access.
Implement Ante/Post Handlers
Use ante handlers for authentication, signature verification, and fee deduction.
Configure appropriate gas limits and minimum gas prices for your chain.
BaseApp has built-in OpenTelemetry support for monitoring.
Transactions Transaction lifecycle and execution
State Management How BaseApp manages state
Modules Building and integrating modules
Consensus ABCI and CometBFT integration