keeper.go

Loc: x/stake/keeper.go

每个模块都有自己的KVstore,用来存储模块执行的需要保存的结果(对bank,就是账户余额...,对于stake 就是pool,还有validator,delegator的一些信息),keeper就是访问和修改KVStore入口。KVStore的状态,决定了程序的运行状态,如果一个节点的KVStore的apphash与其他节点不同,他就无法继续运行。

package stake

import (
    "bytes"

    sdk "github.com/cosmos/cosmos-sdk/types"
    "github.com/cosmos/cosmos-sdk/wire"
    "github.com/cosmos/cosmos-sdk/x/bank"
    abci "github.com/tendermint/abci/types"
)

// keeper of the staking store
type Keeper struct {
    storeKey   sdk.StoreKey
    cdc        *wire.Codec
    coinKeeper bank.Keeper

    // caches
    pool   Pool
    params Params

    // codespace
    codespace sdk.CodespaceType
}

func NewKeeper(cdc *wire.Codec, key sdk.StoreKey, ck bank.Keeper, codespace sdk.CodespaceType) Keeper {
    keeper := Keeper{
        storeKey:   key,
        cdc:        cdc,
        coinKeeper: ck,
        codespace:  codespace,
    }
    return keeper
}

stake中的keeper的struct中你会发现有coinKeeper,这个是对账户KVStore的存取,所以一个专属于模块的keeper中也可以调用其他模块的keeper来进行KVStore的访问。stake模块因为需要对用户账户的KVStore进行存取操作,所以在stake中keeper引用了coinkeeper。当然你需要其他的模块的KVStore,你也可以引入。

  • storeKey 就是你kvstore的name,在app.go中注册的字符串。

  • Pool,Params就是stake模块kvstore需要存取的数据结构

// get the current in-block validator operation counter
func (k Keeper) getCounter(ctx sdk.Context) int16 {
    store := ctx.KVStore(k.storeKey)
    b := store.Get(CounterKey)
    if b == nil {
        return 0
    }
    var counter int16
    err := k.cdc.UnmarshalBinary(b, &counter)
    if err != nil {
        panic(err)
    }
    return counter
}

// set the current in-block validator operation counter
func (k Keeper) setCounter(ctx sdk.Context, counter int16) {
    store := ctx.KVStore(k.storeKey)
    bz, err := k.cdc.MarshalBinary(counter)
    if err != nil {
        panic(err)
    }
    store.Set(CounterKey, bz)
}

getCountersetCounter就是典型的存取。ctx 就是context,保存了模块运行所需要的所有资源,比如kvstore就在里面。根据storeKey来获取对应模块的KVStore

  • getCounter 通过ctx.KVStore获取stake的store。通过store.Get(counter),获取counter(CounterKey = []byte{0x08})对应的值,这个值也是字节数组。然后通过k.cdc.UnmarshalBinary函数获取真实的值,赋值给counter,最后返回counter

  • setCounter 与get操作相反,传入你需要写的值counter,一样获取store,然后用k.cdc.MarshalBinary编码,最后调用store.Set,把bz的值写入CounterKey对应的存储里。

Last updated