Skip to content

Latest commit

 

History

History
123 lines (90 loc) · 5.81 KB

app-init.md

File metadata and controls

123 lines (90 loc) · 5.81 KB

Start your application

Get started by creating a new file: ./app.go. This file is the heart of your deterministic state-machine (blockchain). app.go is where the different modules are initialized and configured into a complete application using the sdk.ModuleBasicManager.

In app.go, you define what the application does when it receives a transaction. But first, it needs to be able to receive transactions in the correct order. This is the role of the Tendermint consensus engine.

Start by importing the necessary dependencies:

package app

import (
	"encoding/json"
	"os"

	"github.com/tendermint/tendermint/libs/log"

	"github.com/cosmos/cosmos-sdk/codec"
	"github.com/cosmos/cosmos-sdk/x/auth"

	"github.com/cosmos/cosmos-sdk/x/auth/genaccounts"

	"github.com/cosmos/cosmos-sdk/x/bank"
	distr "github.com/cosmos/cosmos-sdk/x/distribution"
	"github.com/cosmos/cosmos-sdk/x/params"
	"github.com/cosmos/cosmos-sdk/x/staking"
	"github.com/cosmos/sdk-application-tutorial/x/nameservice"

	bam "github.com/cosmos/cosmos-sdk/baseapp"
	sdk "github.com/cosmos/cosmos-sdk/types"
	abci "github.com/tendermint/tendermint/abci/types"
	cmn "github.com/tendermint/tendermint/libs/common"
	dbm "github.com/tendermint/tendermint/libs/db"
)

Links to godocs for each module and package imported:

  • log: Tendermint's logger.
  • auth: The auth module for the Comsos SDK.
  • dbm: Code for working with the Tendermint database.
  • baseapp: See below

A couple of the packages here are tendermint packages. Tendermint passes transactions from the network to the application through an interface called the ABCI. If you look at the architecture of the blockchain node you are building, it looks like the following:

+---------------------+
|                     |
|     Application     |
|                     |
+--------+---+--------+
         ^   |
         |   | ABCI
         |   v
+--------+---+--------+
|                     |
|                     |
|     Tendermint      |
|                     |
|                     |
+---------------------+

Fortunately, you do not have to implement the ABCI interface. The Cosmos SDK provides a boilerplate implementation of it in the form of baseapp.

Here is what baseapp does:

  • Decode transactions received from the Tendermint consensus engine.
  • Extract messages from transactions and do basic sanity checks.
  • Route the message to the appropriate module so that it can be processed. Note that baseapp has no knowledge of the specific modules you want to use. It is your job to declare such modules in app.go, as you will see later in this tutorial. baseapp only implements the core routing logic that can be applied to any module.
  • Commit if the ABCI message is DeliverTx (CheckTx changes are not persistent).
  • Help set up Beginblock and Endblock, two messages that enable you to define logic executed at the beginning and end of each block. In practice, each module implements its own BeginBlock and EndBlock sub-logic, and the role of the app is to aggregate everything together (Note: you won't be using these messages in your application).
  • Help initialise your state.
  • Help set up queries.

Now you need to create a new custom type nameServiceApp for your application. This type will embed baseapp (embedding in Go similar to inheritance in other languages), meaning it will have access to all of baseapp's methods.

const appName = "nameservice"

var (
	// default home directories for the application CLI
	DefaultCLIHome = os.ExpandEnv("$HOME/.nscli")

	// DefaultNodeHome sets the folder where the applcation data and configuration will be stored
	DefaultNodeHome = os.ExpandEnv("$HOME/.nsd")

	// ModuleBasicManager is in charge of setting up basic module elemnets
	ModuleBasics sdk.ModuleBasicManager
)

type nameServiceApp struct {
    *bam.BaseApp
}

Add a simple constructor for your application:

func NewNameServiceApp(logger log.Logger, db dbm.DB) *nameServiceApp {

    // First define the top level codec that will be shared by the different modules. Note: Codec will be explained later
    cdc := MakeCodec()

    // BaseApp handles interactions with Tendermint through the ABCI protocol
    bApp := bam.NewBaseApp(appName, logger, db, auth.DefaultTxDecoder(cdc))

    var app = &nameServiceApp{
        BaseApp: bApp,
        cdc:     cdc,
    }

    return app
}

Great! You now have the skeleton of your application; however, it still lacks functionality.

baseapp has no knowledge of the routes or user interactions you want to use in your application. The primary role of your application is to define these routes. Another role is to define the initial state. Both these things require that you add modules to your application.

As you have seen in the application design section, you need a couple modules for your nameservice: auth, bank, staking, distribution, slashing and nameservice. The first two already exist, but not the last! The nameservice module will define the bulk of your state machine. The next step is to build it.

In order to complete your application, you need to include modules. Go ahead and start building your nameservice module. You will come back to app.go later.