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