app.go

Loc:cmd/gaia/app/app.go

具体gaiaApp对baseapp的二次封装结构

// Extended ABCI application
type GaiaApp struct {
    *bam.BaseApp
    cdc *wire.Codec

    // keys to access the substores
    keyMain    *sdk.KVStoreKey
    keyAccount *sdk.KVStoreKey
    keyIBC     *sdk.KVStoreKey
    keyStake   *sdk.KVStoreKey

    // Manage getting and setting accounts
    accountMapper sdk.AccountMapper
    coinKeeper    bank.Keeper
    ibcMapper     ibc.Mapper
    stakeKeeper   stake.Keeper
}
  • *bam.BaseApp 这个就是baseapp的基本结构,在他基础上二次开发

  • keyStake *sdk.KVStoreKey KVstore的键类型,这是stake的键,如果你想添加自己的module,你可以添加keyMyModule *sdk.KVStoreKey

  • stakeKeeper stake.Keeper stake.keeper结构(在x/stake/keeper.go里)用来访问和设置kvstore,如果你想要添加自己的module,你可以添加mymoduleKeeper mymodule.Keeper

下面就是GaiaApp的构造,完整代码我拆分开来,讲解起来更方便

func NewGaiaApp(logger log.Logger, db dbm.DB) *GaiaApp {
    cdc := MakeCodec()

    // create your application object
    var app = &GaiaApp{
        BaseApp:    bam.NewBaseApp(appName, cdc, logger, db),
        cdc:        cdc,
        keyMain:    sdk.NewKVStoreKey("main"),
        keyAccount: sdk.NewKVStoreKey("acc"),
        keyIBC:     sdk.NewKVStoreKey("ibc"),
        keyStake:   sdk.NewKVStoreKey("stake"),
    }

常见应用的对象的时候,如果你想加入你自己的mymodule,你需要像stake模块一样(keyStake: sdk.NewKVStoreKey("stake"))添加自己的keyMymodule: sdk.NewKVStoreKey("mymodule")这个key后面会在app.MountStoresIAVL中注册这个名字的stores,每个模块都有自己的名字的kvstore,虽然现在他们其实是公用一个kvstore,他的根是'main',例如stake模块的kvstore是'main':{'stake':{...},'mymodule':{...},...}

    // add handlers
    app.coinKeeper = bank.NewKeeper(app.accountMapper)
    app.ibcMapper = ibc.NewMapper(app.cdc, app.keyIBC, app.RegisterCodespace(ibc.DefaultCodespace))
    app.stakeKeeper = stake.NewKeeper(app.cdc, app.keyStake, app.coinKeeper, app.RegisterCodespace(stake.DefaultCodespace))

上面代码就是注册自己模块的keeper,每个keeper构造的是时候如果你想访问其他模块的kvstore也可以穿入其他模块的keeper,例如stakeKeeper 就传入了app.coinKeeper. 然后我可以模仿stake 添加自己的模块代码如下:

app.mymoduleKeeper = mymodule.NewKeeper(app.cdc, app.mymodule,app.coinKeeper,app.stakeKeeper,app.RegisterCodespace(mymodule.DefaultCodespace))

Keeper在keeper.go中定义。

    // register message routes
    app.Router().
        AddRoute("bank", bank.NewHandler(app.coinKeeper)).
        AddRoute("ibc", ibc.NewHandler(app.ibcMapper, app.coinKeeper)).
        AddRoute("stake", stake.NewHandler(app.stakeKeeper))

接下来上面的代码就是注册自己的handler,模仿stake在app.Router()...后面添加.AddRoute("mymodule",mymodule.NewHandler(app.mymoduleKeeper))这样就成功注册了自己模块的handler.这个在handler.go里面声明定义。

    // initialize BaseApp
    app.SetInitChainer(app.initChainer)
    app.SetEndBlocker(stake.NewEndBlocker(app.stakeKeeper))
    app.MountStoresIAVL(app.keyMain, app.keyAccount, app.keyIBC, app.keyStake)
    app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper, stake.FeeHandler))
    err := app.LoadLatestVersion(app.keyMain)
    if err != nil {
        cmn.Exit(err.Error())
    }

    return app
}

app.SetEndBlocker注册endblock的handler,上面代码接受的是stake的endblocker,当然你可以定义自己的endblocker模块,但是要注意一个baseapp就一个endblocker接口,所以只能注册一个handler,并不像checktx和delivertx可以通过router来路由选择对应的handler处理。 下面AnteHandler同理 最后app.MountStoresIAVL(中加入 app.keymymodule....)

// custom tx codec
func MakeCodec() *wire.Codec {
    var cdc = wire.NewCodec()
    ibc.RegisterWire(cdc)
    bank.RegisterWire(cdc)
    stake.RegisterWire(cdc)
    auth.RegisterWire(cdc)
    sdk.RegisterWire(cdc)
    wire.RegisterCrypto(cdc)
    return cdc
}

这个go-amino序列化的部分,只需要添加自己的模块部分即可mymodule.RegisterWire(cdc) 这个在wire.go里面声明定义

具体细节 大家可以参考我的 app.go-mymodule 模版,不过这个在本大章的末尾,因为我先要编写handler.go,keeper.go...,然后再把他们注册入app.go

Last updated