paramstore refactor base

rm debug code

fix lint

fix hack.go
This commit is contained in:
mossid 2018-08-31 02:03:43 -07:00
parent c4b243142d
commit cc0e2c9523
43 changed files with 885 additions and 836 deletions

View File

@ -88,11 +88,11 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio
// add handlers
app.bankKeeper = bank.NewBaseKeeper(app.accountMapper)
app.paramsKeeper = params.NewKeeper(app.cdc, app.keyParams)
app.stakeKeeper = stake.NewKeeper(app.cdc, app.keyStake, app.tkeyStake, app.bankKeeper, app.RegisterCodespace(stake.DefaultCodespace))
app.slashingKeeper = slashing.NewKeeper(app.cdc, app.keySlashing, app.stakeKeeper, app.paramsKeeper.Getter(), app.RegisterCodespace(slashing.DefaultCodespace))
app.paramsKeeper = params.NewKeeper(app.cdc, app.keyParams, app.tkeyParams)
app.stakeKeeper = stake.NewKeeper(app.cdc, app.keyStake, app.tkeyStake, app.bankKeeper, app.paramsKeeper.Subspace(stake.DefaultParamSpace), app.RegisterCodespace(stake.DefaultCodespace))
app.slashingKeeper = slashing.NewKeeper(app.cdc, app.keySlashing, app.stakeKeeper, app.paramsKeeper.Subspace(slashing.DefaultParamSpace), app.RegisterCodespace(slashing.DefaultCodespace))
app.stakeKeeper = app.stakeKeeper.WithHooks(app.slashingKeeper.Hooks())
app.govKeeper = gov.NewKeeper(app.cdc, app.keyGov, app.paramsKeeper.Setter(), app.bankKeeper, app.stakeKeeper, app.RegisterCodespace(gov.DefaultCodespace))
app.govKeeper = gov.NewKeeper(app.cdc, app.keyGov, app.paramsKeeper, app.paramsKeeper.Subspace(gov.DefaultParamSpace), app.bankKeeper, app.stakeKeeper, app.RegisterCodespace(gov.DefaultCodespace))
app.feeCollectionKeeper = auth.NewFeeCollectionKeeper(app.cdc, app.keyFeeCollection)
// register message routes
@ -184,7 +184,7 @@ func (app *GaiaApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci
}
// load the address to pubkey map
slashing.InitGenesis(ctx, app.slashingKeeper, genesisState.StakeData)
slashing.InitGenesis(ctx, app.slashingKeeper, genesisState.SlashingData, genesisState.StakeData)
gov.InitGenesis(ctx, app.govKeeper, genesisState.GovData)
err = GaiaValidateGenesisState(genesisState)
@ -193,6 +193,11 @@ func (app *GaiaApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci
panic(err)
}
err = slashing.InitGenesis(ctx, app.slashingKeeper, genesisState.SlashingData, genesisState.StakeData)
if err != nil {
panic(err)
}
return abci.ResponseInitChain{
Validators: validators,
}

View File

@ -6,6 +6,7 @@ import (
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/slashing"
"github.com/cosmos/cosmos-sdk/x/stake"
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/libs/db"
@ -21,8 +22,9 @@ func setGenesis(gapp *GaiaApp, accs ...*auth.BaseAccount) error {
}
genesisState := GenesisState{
Accounts: genaccs,
StakeData: stake.DefaultGenesisState(),
Accounts: genaccs,
StakeData: stake.DefaultGenesisState(),
SlashingData: slashing.HubDefaultGenesisState(),
}
stateBytes, err := codec.MarshalJSONIndent(gapp.cdc, genesisState)

View File

@ -12,6 +12,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/gov"
"github.com/cosmos/cosmos-sdk/x/slashing"
"github.com/cosmos/cosmos-sdk/x/stake"
stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types"
@ -32,9 +33,10 @@ var (
// State to Unmarshal
type GenesisState struct {
Accounts []GenesisAccount `json:"accounts"`
StakeData stake.GenesisState `json:"stake"`
GovData gov.GenesisState `json:"gov"`
Accounts []GenesisAccount `json:"accounts"`
StakeData stake.GenesisState `json:"stake"`
GovData gov.GenesisState `json:"gov"`
SlashingData slashing.GenesisState `json:"slashing"`
}
// GenesisAccount doesn't need pubkey or sequence
@ -170,6 +172,8 @@ func GaiaAppGenState(cdc *codec.Codec, appGenTxs []json.RawMessage) (genesisStat
// start with the default staking genesis state
stakeData := stake.DefaultGenesisState()
slashingData := slashing.HubDefaultGenesisState()
// get genesis flag account information
genaccs := make([]GenesisAccount, len(appGenTxs))
for i, appGenTx := range appGenTxs {
@ -192,9 +196,10 @@ func GaiaAppGenState(cdc *codec.Codec, appGenTxs []json.RawMessage) (genesisStat
// create the final app state
genesisState = GenesisState{
Accounts: genaccs,
StakeData: stakeData,
GovData: gov.DefaultGenesisState(),
Accounts: genaccs,
StakeData: stakeData,
GovData: gov.DefaultGenesisState(),
SlashingData: slashingData,
}
return
}

View File

@ -18,6 +18,7 @@ import (
"github.com/cosmos/cosmos-sdk/x/gov"
govsim "github.com/cosmos/cosmos-sdk/x/gov/simulation"
"github.com/cosmos/cosmos-sdk/x/mock/simulation"
"github.com/cosmos/cosmos-sdk/x/slashing"
slashingsim "github.com/cosmos/cosmos-sdk/x/slashing/simulation"
stake "github.com/cosmos/cosmos-sdk/x/stake"
stakesim "github.com/cosmos/cosmos-sdk/x/stake/simulation"
@ -74,9 +75,10 @@ func appStateFn(r *rand.Rand, accs []simulation.Account) json.RawMessage {
stakeGenesis.Params.InflationMax = sdk.NewDec(0)
stakeGenesis.Params.InflationMin = sdk.NewDec(0)
genesis := GenesisState{
Accounts: genesisAccounts,
StakeData: stakeGenesis,
GovData: govGenesis,
Accounts: genesisAccounts,
StakeData: stakeGenesis,
SlashingData: slashing.HubDefaultGenesisState(),
GovData: govGenesis,
}
// Marshal genesis

View File

@ -135,6 +135,7 @@ type GaiaApp struct {
tkeyStake *sdk.TransientStoreKey
keySlashing *sdk.KVStoreKey
keyParams *sdk.KVStoreKey
tkeyParams *sdk.TransientStoreKey
// Manage getting and setting accounts
accountMapper auth.AccountMapper
@ -161,6 +162,7 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, baseAppOptions ...func(*bam.BaseAp
tkeyStake: sdk.NewTransientStoreKey("transient_stake"),
keySlashing: sdk.NewKVStoreKey("slashing"),
keyParams: sdk.NewKVStoreKey("params"),
tkeyParams: sdk.NewTransientStoreKey("transient_params"),
}
// define the accountMapper
@ -172,9 +174,9 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, baseAppOptions ...func(*bam.BaseAp
// add handlers
app.bankKeeper = bank.NewBaseKeeper(app.accountMapper)
app.paramsKeeper = params.NewKeeper(app.cdc, app.keyParams)
app.stakeKeeper = stake.NewKeeper(app.cdc, app.keyStake, app.tkeyStake, app.bankKeeper, app.RegisterCodespace(stake.DefaultCodespace))
app.slashingKeeper = slashing.NewKeeper(app.cdc, app.keySlashing, app.stakeKeeper, app.paramsKeeper.Getter(), app.RegisterCodespace(slashing.DefaultCodespace))
app.paramsKeeper = params.NewKeeper(app.cdc, app.keyParams, app.tkeyParams)
app.stakeKeeper = stake.NewKeeper(app.cdc, app.keyStake, app.tkeyStake, app.bankKeeper, app.paramsKeeper.Subspace(stake.DefaultParamSpace), app.RegisterCodespace(stake.DefaultCodespace))
app.slashingKeeper = slashing.NewKeeper(app.cdc, app.keySlashing, app.stakeKeeper, app.paramsKeeper.Subspace(slashing.DefaultParamSpace), app.RegisterCodespace(slashing.DefaultCodespace))
// register message routes
app.Router().
@ -186,7 +188,8 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, baseAppOptions ...func(*bam.BaseAp
app.SetBeginBlocker(app.BeginBlocker)
app.SetEndBlocker(app.EndBlocker)
app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper, app.feeCollectionKeeper))
app.MountStoresIAVL(app.keyMain, app.keyAccount, app.keyStake, app.keySlashing)
app.MountStoresIAVL(app.keyMain, app.keyAccount, app.keyStake, app.keySlashing, app.keyParams)
app.MountStore(app.tkeyParams, sdk.StoreTypeTransient)
err := app.LoadLatestVersion(app.keyMain)
if err != nil {
cmn.Exit(err.Error())
@ -252,6 +255,11 @@ func (app *GaiaApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci
panic(err) // TODO https://github.com/cosmos/cosmos-sdk/issues/468 // return sdk.ErrGenesisParse("").TraceCause(err, "")
}
err = slashing.InitGenesis(ctx, app.slashingKeeper, genesisState.SlashingData, genesisState.StakeData)
if err != nil {
panic(err)
}
return abci.ResponseInitChain{
Validators: validators,
}

View File

@ -13,13 +13,13 @@ import (
func newGasKVStore() KVStore {
meter := sdk.NewGasMeter(1000)
mem := dbStoreAdapter{dbm.NewMemDB()}
return NewGasKVStore(meter, sdk.DefaultGasConfig(), mem)
return NewGasKVStore(meter, sdk.DefaultKVGasConfig(), mem)
}
func TestGasKVStoreBasic(t *testing.T) {
func TestKVGasKVStoreBasic(t *testing.T) {
mem := dbStoreAdapter{dbm.NewMemDB()}
meter := sdk.NewGasMeter(1000)
st := NewGasKVStore(meter, sdk.DefaultGasConfig(), mem)
st := NewGasKVStore(meter, sdk.DefaultKVGasConfig(), mem)
require.Empty(t, st.Get(keyFmt(1)), "Expected `key1` to be empty")
st.Set(keyFmt(1), valFmt(1))
require.Equal(t, valFmt(1), st.Get(keyFmt(1)))
@ -28,10 +28,10 @@ func TestGasKVStoreBasic(t *testing.T) {
require.Equal(t, meter.GasConsumed(), sdk.Gas(193))
}
func TestGasKVStoreIterator(t *testing.T) {
func TestKVGasKVStoreIterator(t *testing.T) {
mem := dbStoreAdapter{dbm.NewMemDB()}
meter := sdk.NewGasMeter(1000)
st := NewGasKVStore(meter, sdk.DefaultGasConfig(), mem)
st := NewGasKVStore(meter, sdk.DefaultKVGasConfig(), mem)
require.Empty(t, st.Get(keyFmt(1)), "Expected `key1` to be empty")
require.Empty(t, st.Get(keyFmt(2)), "Expected `key2` to be empty")
st.Set(keyFmt(1), valFmt(1))
@ -52,24 +52,24 @@ func TestGasKVStoreIterator(t *testing.T) {
require.Equal(t, meter.GasConsumed(), sdk.Gas(384))
}
func TestGasKVStoreOutOfGasSet(t *testing.T) {
func TestKVGasKVStoreOutOfGasSet(t *testing.T) {
mem := dbStoreAdapter{dbm.NewMemDB()}
meter := sdk.NewGasMeter(0)
st := NewGasKVStore(meter, sdk.DefaultGasConfig(), mem)
st := NewGasKVStore(meter, sdk.DefaultKVGasConfig(), mem)
require.Panics(t, func() { st.Set(keyFmt(1), valFmt(1)) }, "Expected out-of-gas")
}
func TestGasKVStoreOutOfGasIterator(t *testing.T) {
func TestKVGasKVStoreOutOfGasIterator(t *testing.T) {
mem := dbStoreAdapter{dbm.NewMemDB()}
meter := sdk.NewGasMeter(200)
st := NewGasKVStore(meter, sdk.DefaultGasConfig(), mem)
st := NewGasKVStore(meter, sdk.DefaultKVGasConfig(), mem)
st.Set(keyFmt(1), valFmt(1))
iterator := st.Iterator(nil, nil)
iterator.Next()
require.Panics(t, func() { iterator.Value() }, "Expected out-of-gas")
}
func testGasKVStoreWrap(t *testing.T, store KVStore) {
func testKVGasKVStoreWrap(t *testing.T, store KVStore) {
meter := sdk.NewGasMeter(10000)
store = store.Gas(meter, sdk.GasConfig{HasCost: 10})
@ -84,22 +84,22 @@ func testGasKVStoreWrap(t *testing.T, store KVStore) {
require.Equal(t, int64(40), meter.GasConsumed())
}
func TestGasKVStoreWrap(t *testing.T) {
func TestKVGasKVStoreWrap(t *testing.T) {
db := dbm.NewMemDB()
tree, _ := newTree(t, db)
iavl := newIAVLStore(tree, numRecent, storeEvery)
testGasKVStoreWrap(t, iavl)
testKVGasKVStoreWrap(t, iavl)
st := NewCacheKVStore(iavl)
testGasKVStoreWrap(t, st)
testKVGasKVStoreWrap(t, st)
pref := st.Prefix([]byte("prefix"))
testGasKVStoreWrap(t, pref)
testKVGasKVStoreWrap(t, pref)
dsa := dbStoreAdapter{dbm.NewMemDB()}
testGasKVStoreWrap(t, dsa)
testKVGasKVStoreWrap(t, dsa)
ts := newTransientStore()
testGasKVStoreWrap(t, ts)
testKVGasKVStoreWrap(t, ts)
}

View File

@ -13,6 +13,18 @@ type prefixStore struct {
prefix []byte
}
func clone(bz []byte) (res []byte) {
res = make([]byte, len(bz))
copy(res, bz)
return
}
func (s prefixStore) key(key []byte) (res []byte) {
res = clone(s.prefix)
res = append(res, key...)
return
}
// Implements Store
func (s prefixStore) GetStoreType() StoreType {
return s.parent.GetStoreType()
@ -30,22 +42,23 @@ func (s prefixStore) CacheWrapWithTrace(w io.Writer, tc TraceContext) CacheWrap
// Implements KVStore
func (s prefixStore) Get(key []byte) []byte {
return s.parent.Get(append(s.prefix, key...))
res := s.parent.Get(s.key(key))
return res
}
// Implements KVStore
func (s prefixStore) Has(key []byte) bool {
return s.parent.Has(append(s.prefix, key...))
return s.parent.Has(s.key(key))
}
// Implements KVStore
func (s prefixStore) Set(key, value []byte) {
s.parent.Set(append(s.prefix, key...), value)
s.parent.Set(s.key(key), value)
}
// Implements KVStore
func (s prefixStore) Delete(key []byte) {
s.parent.Delete(append(s.prefix, key...))
s.parent.Delete(s.key(key))
}
// Implements KVStore
@ -60,27 +73,40 @@ func (s prefixStore) Gas(meter GasMeter, config GasConfig) KVStore {
// Implements KVStore
func (s prefixStore) Iterator(start, end []byte) Iterator {
newstart := clone(s.prefix)
newstart = append(newstart, start...)
var newend []byte
if end == nil {
end = sdk.PrefixEndBytes(s.prefix)
newend = sdk.PrefixEndBytes(s.prefix)
} else {
end = append(s.prefix, end...)
newend = clone(s.prefix)
newend = append(newend, end...)
}
return prefixIterator{
prefix: s.prefix,
iter: s.parent.Iterator(append(s.prefix, start...), end),
iter: s.parent.Iterator(newstart, newend),
}
}
// Implements KVStore
func (s prefixStore) ReverseIterator(start, end []byte) Iterator {
newstart := make([]byte, len(s.prefix), len(start))
copy(newstart, s.prefix)
newstart = append(newstart, start...)
newend := make([]byte, len(s.prefix)+len(end))
if end == nil {
end = sdk.PrefixEndBytes(s.prefix)
newend = sdk.PrefixEndBytes(s.prefix)
} else {
end = append(s.prefix, end...)
copy(newend, s.prefix)
newend = append(newend, end...)
}
return prefixIterator{
prefix: s.prefix,
iter: s.parent.ReverseIterator(start, end),
iter: s.parent.ReverseIterator(newstart, newend),
}
}

View File

@ -81,7 +81,7 @@ func TestCacheKVStorePrefix(t *testing.T) {
func TestGasKVStorePrefix(t *testing.T) {
meter := sdk.NewGasMeter(100000000)
mem := dbStoreAdapter{dbm.NewMemDB()}
gasStore := NewGasKVStore(meter, sdk.DefaultGasConfig(), mem)
gasStore := NewGasKVStore(meter, sdk.DefaultKVGasConfig(), mem)
testPrefixStore(t, gasStore, []byte("test"))
}

View File

@ -48,6 +48,8 @@ func NewContext(ms MultiStore, header abci.Header, isCheckTx bool, logger log.Lo
c = c.WithVoteInfos(nil)
c = c.WithGasMeter(NewInfiniteGasMeter())
c = c.WithMinimumFees(Coins{})
c = c.WithKVGasConfig(KVGasConfig())
c = c.WithTransientGasConfig(TransientGasConfig())
return c
}
@ -73,12 +75,12 @@ func (c Context) Value(key interface{}) interface{} {
// KVStore fetches a KVStore from the MultiStore.
func (c Context) KVStore(key StoreKey) KVStore {
return c.multiStore().GetKVStore(key).Gas(c.GasMeter(), cachedDefaultGasConfig)
return c.multiStore().GetKVStore(key).Gas(c.GasMeter(), c.KVGasConfig())
}
// TransientStore fetches a TransientStore from the MultiStore.
func (c Context) TransientStore(key StoreKey) KVStore {
return c.multiStore().GetKVStore(key).Gas(c.GasMeter(), cachedTransientGasConfig)
return c.multiStore().GetKVStore(key).Gas(c.GasMeter(), c.TransientGasConfig())
}
//----------------------------------------
@ -141,6 +143,8 @@ const (
contextKeyVoteInfos
contextKeyGasMeter
contextKeyMinimumFees
contextKeyKVGasConfig
contextKeyTransientGasConfig
)
// NOTE: Do not expose MultiStore.
@ -176,6 +180,12 @@ func (c Context) MinimumFees() Coins { return c.Value(contextKeyMinimumFees).(Co
func (c Context) WithMultiStore(ms MultiStore) Context { return c.withValue(contextKeyMultiStore, ms) }
func (c Context) KVGasConfig() GasConfig { return c.Value(contextKeyKVGasConfig).(GasConfig) }
func (c Context) TransientGasConfig() GasConfig {
return c.Value(contextKeyTransientGasConfig).(GasConfig)
}
func (c Context) WithBlockHeader(header abci.Header) Context {
var _ proto.Message = &header // for cloning.
return c.withValue(contextKeyBlockHeader, header)
@ -212,6 +222,12 @@ func (c Context) WithIsCheckTx(isCheckTx bool) Context {
func (c Context) WithMinimumFees(minFees Coins) Context {
return c.withValue(contextKeyMinimumFees, minFees)
}
func (c Context) WithKVGasConfig(config GasConfig) Context {
return c.withValue(contextKeyKVGasConfig, config)
}
func (c Context) WithTransientGasConfig(config GasConfig) Context {
return c.withValue(contextKeyTransientGasConfig, config)
}
// Cache the multistore and return a new cached context. The cached context is
// written to the context when writeCache is called.

View File

@ -13,7 +13,7 @@ const (
)
var (
cachedDefaultGasConfig = DefaultGasConfig()
cachedKVGasConfig = KVGasConfig()
cachedTransientGasConfig = TransientGasConfig()
)
@ -86,8 +86,8 @@ type GasConfig struct {
IterNextCostFlat Gas
}
// DefaultGasConfig returns a default gas config for KVStores.
func DefaultGasConfig() GasConfig {
// KVGasConfig returns a default gas config for KVStores.
func KVGasConfig() GasConfig {
return GasConfig{
HasCost: 10,
DeleteCost: 10,
@ -103,5 +103,5 @@ func DefaultGasConfig() GasConfig {
// TransientGasConfig returns a default gas config for TransientStores.
func TransientGasConfig() GasConfig {
// TODO: define gasconfig for transient stores
return DefaultGasConfig()
return KVGasConfig()
}

View File

@ -9,15 +9,28 @@ import (
// nolint
const (
ParamStoreKeyDepositProcedure = "gov/depositprocedure"
ParamStoreKeyVotingProcedure = "gov/votingprocedure"
ParamStoreKeyTallyingProcedure = "gov/tallyingprocedure"
DefaultParamSpace = "gov"
)
// nolint - Paramstore key constructor
func ParamStoreKeyDepositProcedure() params.Key { return params.NewKey("depositprocedure") }
func ParamStoreKeyVotingProcedure() params.Key { return params.NewKey("votingprocedure") }
func ParamStoreKeyTallyingProcedure() params.Key { return params.NewKey("tallyingprocedure") }
// Cached parameter store keys
var (
paramStoreKeyDepositProcedure = ParamStoreKeyDepositProcedure()
paramStoreKeyVotingProcedure = ParamStoreKeyVotingProcedure()
paramStoreKeyTallyingProcedure = ParamStoreKeyTallyingProcedure()
)
// Governance Keeper
type Keeper struct {
// The reference to the ParamSetter to get and set Global Params
ps params.Setter
// The reference to the Param Keeper to get and set Global Params
pk params.Keeper
// The reference to the Paramstore to get and set gov specific params
ps params.Space
// The reference to the CoinKeeper to modify balances
ck bank.Keeper
@ -43,9 +56,10 @@ type Keeper struct {
// - depositing funds into proposals, and activating upon sufficient funds being deposited
// - users voting on proposals, with weight proportional to stake in the system
// - and tallying the result of the vote.
func NewKeeper(cdc *codec.Codec, key sdk.StoreKey, ps params.Setter, ck bank.Keeper, ds sdk.DelegationSet, codespace sdk.CodespaceType) Keeper {
func NewKeeper(cdc *codec.Codec, key sdk.StoreKey, pk params.Keeper, ps params.Space, ck bank.Keeper, ds sdk.DelegationSet, codespace sdk.CodespaceType) Keeper {
return Keeper{
storeKey: key,
pk: pk,
ps: ps,
ck: ck,
ds: ds,
@ -210,7 +224,7 @@ func (keeper Keeper) activateVotingPeriod(ctx sdk.Context, proposal Proposal) {
// nolint: errcheck
func (keeper Keeper) GetDepositProcedure(ctx sdk.Context) DepositProcedure {
var depositProcedure DepositProcedure
keeper.ps.Get(ctx, ParamStoreKeyDepositProcedure, &depositProcedure)
keeper.ps.Get(ctx, paramStoreKeyDepositProcedure, &depositProcedure)
return depositProcedure
}
@ -218,7 +232,7 @@ func (keeper Keeper) GetDepositProcedure(ctx sdk.Context) DepositProcedure {
// nolint: errcheck
func (keeper Keeper) GetVotingProcedure(ctx sdk.Context) VotingProcedure {
var votingProcedure VotingProcedure
keeper.ps.Get(ctx, ParamStoreKeyVotingProcedure, &votingProcedure)
keeper.ps.Get(ctx, paramStoreKeyVotingProcedure, &votingProcedure)
return votingProcedure
}
@ -226,23 +240,23 @@ func (keeper Keeper) GetVotingProcedure(ctx sdk.Context) VotingProcedure {
// nolint: errcheck
func (keeper Keeper) GetTallyingProcedure(ctx sdk.Context) TallyingProcedure {
var tallyingProcedure TallyingProcedure
keeper.ps.Get(ctx, ParamStoreKeyTallyingProcedure, &tallyingProcedure)
keeper.ps.Get(ctx, paramStoreKeyTallyingProcedure, &tallyingProcedure)
return tallyingProcedure
}
// nolint: errcheck
func (keeper Keeper) setDepositProcedure(ctx sdk.Context, depositProcedure DepositProcedure) {
keeper.ps.Set(ctx, ParamStoreKeyDepositProcedure, &depositProcedure)
keeper.ps.Set(ctx, paramStoreKeyDepositProcedure, &depositProcedure)
}
// nolint: errcheck
func (keeper Keeper) setVotingProcedure(ctx sdk.Context, votingProcedure VotingProcedure) {
keeper.ps.Set(ctx, ParamStoreKeyVotingProcedure, &votingProcedure)
keeper.ps.Set(ctx, paramStoreKeyVotingProcedure, &votingProcedure)
}
// nolint: errcheck
func (keeper Keeper) setTallyingProcedure(ctx sdk.Context, tallyingProcedure TallyingProcedure) {
keeper.ps.Set(ctx, ParamStoreKeyTallyingProcedure, &tallyingProcedure)
keeper.ps.Set(ctx, paramStoreKeyTallyingProcedure, &tallyingProcedure)
}
// =====================================================

View File

@ -28,16 +28,19 @@ func TestGovWithRandomMessages(t *testing.T) {
stakeTKey := sdk.NewTransientStoreKey("transient_stake")
stakeKeeper := stake.NewKeeper(mapp.Cdc, stakeKey, stakeTKey, bankKeeper, stake.DefaultCodespace)
paramKey := sdk.NewKVStoreKey("params")
paramKeeper := params.NewKeeper(mapp.Cdc, paramKey)
paramTKey := sdk.NewTransientStoreKey("transient_params")
paramKeeper := params.NewKeeper(mapp.Cdc, paramKey, paramTKey)
stakeKey := sdk.NewKVStoreKey("stake")
stakeKeeper := stake.NewKeeper(mapp.Cdc, stakeKey, coinKeeper, paramKeeper.Subspace(stake.DefaultParamSpace), stake.DefaultCodespace)
govKey := sdk.NewKVStoreKey("gov")
govKeeper := gov.NewKeeper(mapp.Cdc, govKey, paramKeeper.Setter(), bankKeeper, stakeKeeper, gov.DefaultCodespace)
govKeeper := gov.NewKeeper(mapp.Cdc, govKey, paramKeeper, paramKeeper.Subspace(gov.DefaultParamSpace), bankKeeper, stakeKeeper, gov.DefaultCodespace)
mapp.Router().AddRoute("gov", gov.NewHandler(govKeeper))
mapp.SetEndBlocker(func(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock {
gov.EndBlocker(ctx, govKeeper)
return abci.ResponseEndBlock{}
})
err := mapp.CompleteSetup(stakeKey, stakeTKey, paramKey, govKey)
err := mapp.CompleteSetup(stakeKey, stakeTKey, paramKey, paramTKey, govKey)
if err != nil {
panic(err)
}

View File

@ -27,20 +27,22 @@ func getMockApp(t *testing.T, numGenAccs int) (*mock.App, Keeper, stake.Keeper,
RegisterCodec(mapp.Cdc)
keyGlobalParams := sdk.NewKVStoreKey("params")
tkeyGlobalParams := sdk.NewTransientStoreKey("transient_params")
keyStake := sdk.NewKVStoreKey("stake")
tkeyStake := sdk.NewTransientStoreKey("transient_stake")
keyGov := sdk.NewKVStoreKey("gov")
pk := params.NewKeeper(mapp.Cdc, keyGlobalParams)
pk := params.NewKeeper(mapp.Cdc, keyGlobalParams, tkeyGlobalParams)
ck := bank.NewBaseKeeper(mapp.AccountMapper)
sk := stake.NewKeeper(mapp.Cdc, keyStake, tkeyStake, ck, mapp.RegisterCodespace(stake.DefaultCodespace))
keeper := NewKeeper(mapp.Cdc, keyGov, pk.Setter(), ck, sk, DefaultCodespace)
sk := stake.NewKeeper(mapp.Cdc, keyStake, tkeyStake, ck, pk.Subspace(stake.DefaultParamSpace), mapp.RegisterCodespace(stake.DefaultCodespace))
keeper := NewKeeper(mapp.Cdc, keyGov, pk, pk.Subspace("testgov"), ck, sk, DefaultCodespace)
mapp.Router().AddRoute("gov", NewHandler(keeper))
mapp.SetEndBlocker(getEndBlocker(keeper))
mapp.SetInitChainer(getInitChainer(mapp, keeper, sk))
require.NoError(t, mapp.CompleteSetup(keyStake, keyGov, keyGlobalParams, tkeyStake))
require.NoError(t, mapp.CompleteSetup(keyStake, tkeyStake, keyGov, keyGlobalParams, tkeyGlobalParams))
genAccs, addrs, pubKeys, privKeys := mock.CreateGenAccounts(numGenAccs, sdk.Coins{sdk.NewInt64Coin("steak", 42)})

View File

@ -0,0 +1,25 @@
package utils
import (
"github.com/cosmos/cosmos-sdk/client/context"
"github.com/cosmos/cosmos-sdk/x/params"
)
// TODO: remove hardcoded storename
const storeName = "params"
// Query parameters from node with CLIContext
func QueryParams(cliCtx context.CLIContext, subStoreName string, ps params.ParamStruct) error {
m := make(map[string][]byte)
for _, p := range ps.KeyFieldPairs() {
key := p.Key.String()
bz, err := cliCtx.QueryStore([]byte(subStoreName+"/"+key), storeName)
if err != nil {
return err
}
m[key] = bz
}
return params.UnmarshalParamsFromMap(m, cliCtx.Codec, ps)
}

View File

@ -1,406 +1,53 @@
package params
import (
"fmt"
"reflect"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/params/space"
)
// Keeper manages global parameter store
// Keeper of the global paramstore
type Keeper struct {
cdc *codec.Codec
key sdk.StoreKey
cdc *codec.Codec
key sdk.StoreKey
tkey sdk.StoreKey
spaces map[string]*Space
}
// NewKeeper constructs a new Keeper
func NewKeeper(cdc *codec.Codec, key sdk.StoreKey) Keeper {
return Keeper{
cdc: cdc,
key: key,
}
}
// NewKeeper construct a params keeper
func NewKeeper(cdc *codec.Codec, key *sdk.KVStoreKey, tkey *sdk.TransientStoreKey) (k Keeper) {
k = Keeper{
cdc: cdc,
key: key,
tkey: tkey,
// InitKeeper constructs a new Keeper with initial parameters
// nolint: errcheck
func InitKeeper(ctx sdk.Context, cdc *codec.Codec, key sdk.StoreKey, params ...interface{}) Keeper {
if len(params)%2 != 0 {
panic("Odd params list length for InitKeeper")
}
k := NewKeeper(cdc, key)
for i := 0; i < len(params); i += 2 {
k.set(ctx, params[i].(string), params[i+1])
spaces: make(map[string]*Space),
}
return k
}
// get automatically unmarshalls parameter to pointer
func (k Keeper) get(ctx sdk.Context, key string, ptr interface{}) error {
store := ctx.KVStore(k.key)
bz := store.Get([]byte(key))
return k.cdc.UnmarshalBinary(bz, ptr)
}
// getRaw returns raw byte slice
func (k Keeper) getRaw(ctx sdk.Context, key string) []byte {
store := ctx.KVStore(k.key)
return store.Get([]byte(key))
}
// set automatically marshalls and type check parameter
func (k Keeper) set(ctx sdk.Context, key string, param interface{}) error {
store := ctx.KVStore(k.key)
bz := store.Get([]byte(key))
if bz != nil {
ptrty := reflect.PtrTo(reflect.TypeOf(param))
ptr := reflect.New(ptrty).Interface()
if k.cdc.UnmarshalBinary(bz, ptr) != nil {
return fmt.Errorf("Type mismatch with stored param and provided param")
}
// Allocate substore used for keepers
func (k Keeper) Subspace(space string) Space {
_, ok := k.spaces[space]
if ok {
panic("subspace already occupied")
}
bz, err := k.cdc.MarshalBinary(param)
if err != nil {
return err
return k.UnsafeSubspace(space)
}
// Get substore without checking existing allocation
func (k Keeper) UnsafeSubspace(spacename string) Space {
if spacename == "" {
panic("cannot use empty string for subspace")
}
store.Set([]byte(key), bz)
return nil
}
space := space.NewSpace(k.cdc, k.key, k.tkey, spacename)
// setRaw sets raw byte slice
func (k Keeper) setRaw(ctx sdk.Context, key string, param []byte) {
store := ctx.KVStore(k.key)
store.Set([]byte(key), param)
}
k.spaces[spacename] = &space
// Getter returns readonly struct
func (k Keeper) Getter() Getter {
return Getter{k}
}
// Setter returns read/write struct
func (k Keeper) Setter() Setter {
return Setter{Getter{k}}
}
// Getter exposes methods related with only getting params
type Getter struct {
k Keeper
}
// Get exposes get
func (k Getter) Get(ctx sdk.Context, key string, ptr interface{}) error {
return k.k.get(ctx, key, ptr)
}
// GetRaw exposes getRaw
func (k Getter) GetRaw(ctx sdk.Context, key string) []byte {
return k.k.getRaw(ctx, key)
}
// GetString is helper function for string params
func (k Getter) GetString(ctx sdk.Context, key string) (res string, err error) {
store := ctx.KVStore(k.k.key)
bz := store.Get([]byte(key))
err = k.k.cdc.UnmarshalBinary(bz, &res)
return
}
// GetBool is helper function for bool params
func (k Getter) GetBool(ctx sdk.Context, key string) (res bool, err error) {
store := ctx.KVStore(k.k.key)
bz := store.Get([]byte(key))
err = k.k.cdc.UnmarshalBinary(bz, &res)
return
}
// GetInt16 is helper function for int16 params
func (k Getter) GetInt16(ctx sdk.Context, key string) (res int16, err error) {
store := ctx.KVStore(k.k.key)
bz := store.Get([]byte(key))
err = k.k.cdc.UnmarshalBinary(bz, &res)
return
}
// GetInt32 is helper function for int32 params
func (k Getter) GetInt32(ctx sdk.Context, key string) (res int32, err error) {
store := ctx.KVStore(k.k.key)
bz := store.Get([]byte(key))
err = k.k.cdc.UnmarshalBinary(bz, &res)
return
}
// GetInt64 is helper function for int64 params
func (k Getter) GetInt64(ctx sdk.Context, key string) (res int64, err error) {
store := ctx.KVStore(k.k.key)
bz := store.Get([]byte(key))
err = k.k.cdc.UnmarshalBinary(bz, &res)
return
}
// GetUint16 is helper function for uint16 params
func (k Getter) GetUint16(ctx sdk.Context, key string) (res uint16, err error) {
store := ctx.KVStore(k.k.key)
bz := store.Get([]byte(key))
err = k.k.cdc.UnmarshalBinary(bz, &res)
return
}
// GetUint32 is helper function for uint32 params
func (k Getter) GetUint32(ctx sdk.Context, key string) (res uint32, err error) {
store := ctx.KVStore(k.k.key)
bz := store.Get([]byte(key))
err = k.k.cdc.UnmarshalBinary(bz, &res)
return
}
// GetUint64 is helper function for uint64 params
func (k Getter) GetUint64(ctx sdk.Context, key string) (res uint64, err error) {
store := ctx.KVStore(k.k.key)
bz := store.Get([]byte(key))
err = k.k.cdc.UnmarshalBinary(bz, &res)
return
}
// GetInt is helper function for sdk.Int params
func (k Getter) GetInt(ctx sdk.Context, key string) (res sdk.Int, err error) {
store := ctx.KVStore(k.k.key)
bz := store.Get([]byte(key))
err = k.k.cdc.UnmarshalBinary(bz, &res)
return
}
// GetUint is helper function for sdk.Uint params
func (k Getter) GetUint(ctx sdk.Context, key string) (res sdk.Uint, err error) {
store := ctx.KVStore(k.k.key)
bz := store.Get([]byte(key))
err = k.k.cdc.UnmarshalBinary(bz, &res)
return
}
// GetDec is helper function for decimal params
func (k Getter) GetDec(ctx sdk.Context, key string) (res sdk.Dec, err error) {
store := ctx.KVStore(k.k.key)
bz := store.Get([]byte(key))
err = k.k.cdc.UnmarshalBinary(bz, &res)
return
}
// GetStringWithDefault is helper function for string params with default value
func (k Getter) GetStringWithDefault(ctx sdk.Context, key string, def string) (res string) {
store := ctx.KVStore(k.k.key)
bz := store.Get([]byte(key))
if bz == nil {
return def
}
k.k.cdc.MustUnmarshalBinary(bz, &res)
return
}
// GetBoolWithDefault is helper function for bool params with default value
func (k Getter) GetBoolWithDefault(ctx sdk.Context, key string, def bool) (res bool) {
store := ctx.KVStore(k.k.key)
bz := store.Get([]byte(key))
if bz == nil {
return def
}
k.k.cdc.MustUnmarshalBinary(bz, &res)
return
}
// GetInt16WithDefault is helper function for int16 params with default value
func (k Getter) GetInt16WithDefault(ctx sdk.Context, key string, def int16) (res int16) {
store := ctx.KVStore(k.k.key)
bz := store.Get([]byte(key))
if bz == nil {
return def
}
k.k.cdc.MustUnmarshalBinary(bz, &res)
return
}
// GetInt32WithDefault is helper function for int32 params with default value
func (k Getter) GetInt32WithDefault(ctx sdk.Context, key string, def int32) (res int32) {
store := ctx.KVStore(k.k.key)
bz := store.Get([]byte(key))
if bz == nil {
return def
}
k.k.cdc.MustUnmarshalBinary(bz, &res)
return
}
// GetInt64WithDefault is helper function for int64 params with default value
func (k Getter) GetInt64WithDefault(ctx sdk.Context, key string, def int64) (res int64) {
store := ctx.KVStore(k.k.key)
bz := store.Get([]byte(key))
if bz == nil {
return def
}
k.k.cdc.MustUnmarshalBinary(bz, &res)
return
}
// GetUint16WithDefault is helper function for uint16 params with default value
func (k Getter) GetUint16WithDefault(ctx sdk.Context, key string, def uint16) (res uint16) {
store := ctx.KVStore(k.k.key)
bz := store.Get([]byte(key))
if bz == nil {
return def
}
k.k.cdc.MustUnmarshalBinary(bz, &res)
return
}
// GetUint32WithDefault is helper function for uint32 params with default value
func (k Getter) GetUint32WithDefault(ctx sdk.Context, key string, def uint32) (res uint32) {
store := ctx.KVStore(k.k.key)
bz := store.Get([]byte(key))
if bz == nil {
return def
}
k.k.cdc.MustUnmarshalBinary(bz, &res)
return
}
// GetUint64WithDefault is helper function for uint64 params with default value
func (k Getter) GetUint64WithDefault(ctx sdk.Context, key string, def uint64) (res uint64) {
store := ctx.KVStore(k.k.key)
bz := store.Get([]byte(key))
if bz == nil {
return def
}
k.k.cdc.MustUnmarshalBinary(bz, &res)
return
}
// GetIntWithDefault is helper function for sdk.Int params with default value
func (k Getter) GetIntWithDefault(ctx sdk.Context, key string, def sdk.Int) (res sdk.Int) {
store := ctx.KVStore(k.k.key)
bz := store.Get([]byte(key))
if bz == nil {
return def
}
k.k.cdc.MustUnmarshalBinary(bz, &res)
return
}
// GetUintWithDefault is helper function for sdk.Uint params with default value
func (k Getter) GetUintWithDefault(ctx sdk.Context, key string, def sdk.Uint) (res sdk.Uint) {
store := ctx.KVStore(k.k.key)
bz := store.Get([]byte(key))
if bz == nil {
return def
}
k.k.cdc.MustUnmarshalBinary(bz, &res)
return
}
// GetDecWithDefault is helper function for sdk.Dec params with default value
func (k Getter) GetDecWithDefault(ctx sdk.Context, key string, def sdk.Dec) (res sdk.Dec) {
store := ctx.KVStore(k.k.key)
bz := store.Get([]byte(key))
if bz == nil {
return def
}
k.k.cdc.MustUnmarshalBinary(bz, &res)
return
}
// Setter exposes all methods including Set
type Setter struct {
Getter
}
// Set exposes set
func (k Setter) Set(ctx sdk.Context, key string, param interface{}) error {
return k.k.set(ctx, key, param)
}
// SetRaw exposes setRaw
func (k Setter) SetRaw(ctx sdk.Context, key string, param []byte) {
k.k.setRaw(ctx, key, param)
}
// SetString is helper function for string params
func (k Setter) SetString(ctx sdk.Context, key string, param string) {
if err := k.k.set(ctx, key, param); err != nil {
panic(err)
}
}
// SetBool is helper function for bool params
func (k Setter) SetBool(ctx sdk.Context, key string, param bool) {
if err := k.k.set(ctx, key, param); err != nil {
panic(err)
}
}
// SetInt16 is helper function for int16 params
func (k Setter) SetInt16(ctx sdk.Context, key string, param int16) {
if err := k.k.set(ctx, key, param); err != nil {
panic(err)
}
}
// SetInt32 is helper function for int32 params
func (k Setter) SetInt32(ctx sdk.Context, key string, param int32) {
if err := k.k.set(ctx, key, param); err != nil {
panic(err)
}
}
// SetInt64 is helper function for int64 params
func (k Setter) SetInt64(ctx sdk.Context, key string, param int64) {
if err := k.k.set(ctx, key, param); err != nil {
panic(err)
}
}
// SetUint16 is helper function for uint16 params
func (k Setter) SetUint16(ctx sdk.Context, key string, param uint16) {
if err := k.k.set(ctx, key, param); err != nil {
panic(err)
}
}
// SetUint32 is helper function for uint32 params
func (k Setter) SetUint32(ctx sdk.Context, key string, param uint32) {
if err := k.k.set(ctx, key, param); err != nil {
panic(err)
}
}
// SetUint64 is helper function for uint64 params
func (k Setter) SetUint64(ctx sdk.Context, key string, param uint64) {
if err := k.k.set(ctx, key, param); err != nil {
panic(err)
}
}
// SetInt is helper function for sdk.Int params
func (k Setter) SetInt(ctx sdk.Context, key string, param sdk.Int) {
if err := k.k.set(ctx, key, param); err != nil {
panic(err)
}
}
// SetUint is helper function for sdk.Uint params
func (k Setter) SetUint(ctx sdk.Context, key string, param sdk.Uint) {
if err := k.k.set(ctx, key, param); err != nil {
panic(err)
}
}
// SetDec is helper function for decimal params
func (k Setter) SetDec(ctx sdk.Context, key string, param sdk.Dec) {
if err := k.k.set(ctx, key, param); err != nil {
panic(err)
}
return space
}

View File

@ -1,9 +1,10 @@
package params
import (
"reflect"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
abci "github.com/tendermint/tendermint/abci/types"
dbm "github.com/tendermint/tendermint/libs/db"
@ -14,267 +15,123 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
)
func defaultContext(key sdk.StoreKey) sdk.Context {
func defaultContext(key sdk.StoreKey, tkey sdk.StoreKey) sdk.Context {
db := dbm.NewMemDB()
cms := store.NewCommitMultiStore(db)
cms.MountStoreWithDB(key, sdk.StoreTypeIAVL, db)
cms.MountStoreWithDB(tkey, sdk.StoreTypeTransient, db)
cms.LoadLatestVersion()
ctx := sdk.NewContext(cms, abci.Header{}, false, log.NewNopLogger())
return ctx
}
type s struct{}
func createTestCodec() *codec.Codec {
cdc := codec.NewCodec()
sdk.RegisterWire(cdc)
cdc.RegisterConcrete(s{}, "test/s", nil)
return cdc
}
func TestKeeper(t *testing.T) {
kvs := []struct {
key string
key Key
param int64
}{
{"key1", 10},
{"key2", 55},
{"key3", 182},
{"key4", 17582},
{"key5", 2768554},
{NewKey("key1"), 10},
{NewKey("key2"), 55},
{NewKey("key3"), 182},
{NewKey("key4"), 17582},
{NewKey("key5"), 2768554},
{NewKey("space1", "key1"), 1157279},
{NewKey("space1", "key2"), 9058701},
}
skey := sdk.NewKVStoreKey("test")
ctx := defaultContext(skey)
setter := NewKeeper(codec.New(), skey).Setter()
tkey := sdk.NewTransientStoreKey("transient_test")
ctx := defaultContext(skey, tkey)
space := NewKeeper(codec.NewCodec(), skey, tkey).Subspace("test")
for _, kv := range kvs {
err := setter.Set(ctx, kv.key, kv.param)
assert.Nil(t, err)
err := space.Set(ctx, kv.key, kv.param)
require.Nil(t, err)
}
for _, kv := range kvs {
var param int64
err := setter.Get(ctx, kv.key, &param)
assert.Nil(t, err)
assert.Equal(t, kv.param, param)
require.NotPanics(t, func() { space.Get(ctx, kv.key, &param) })
require.Equal(t, kv.param, param)
}
cdc := codec.New()
for _, kv := range kvs {
var param int64
bz := setter.GetRaw(ctx, kv.key)
err := cdc.UnmarshalBinary(bz, &param)
assert.Nil(t, err)
assert.Equal(t, kv.param, param)
bz := space.GetRaw(ctx, kv.key)
err := cdc.UnmarshalJSON(bz, &param)
require.Nil(t, err)
require.Equal(t, kv.param, param)
}
for _, kv := range kvs {
var param bool
err := setter.Get(ctx, kv.key, &param)
assert.NotNil(t, err)
require.Panics(t, func() { space.Get(ctx, kv.key, &param) })
}
for _, kv := range kvs {
err := setter.Set(ctx, kv.key, true)
assert.NotNil(t, err)
err := space.Set(ctx, kv.key, true)
require.NotNil(t, err)
}
}
func TestGetter(t *testing.T) {
func TestGet(t *testing.T) {
key := sdk.NewKVStoreKey("test")
ctx := defaultContext(key)
keeper := NewKeeper(codec.New(), key)
tkey := sdk.NewTransientStoreKey("transient_test")
ctx := defaultContext(key, tkey)
keeper := NewKeeper(createTestCodec(), key, tkey)
g := keeper.Getter()
s := keeper.Setter()
space := keeper.Subspace("test")
kvs := []struct {
key string
key Key
param interface{}
zero interface{}
ptr interface{}
}{
{"string", "test"},
{"bool", true},
{"int16", int16(1)},
{"int32", int32(1)},
{"int64", int64(1)},
{"uint16", uint16(1)},
{"uint32", uint32(1)},
{"uint64", uint64(1)},
{"int", sdk.NewInt(1)},
{"uint", sdk.NewUint(1)},
{"rat", sdk.NewDec(1)},
{NewKey("string"), "test", "", new(string)},
{NewKey("bool"), true, false, new(bool)},
{NewKey("int16"), int16(1), int16(0), new(int16)},
{NewKey("int32"), int32(1), int32(0), new(int32)},
{NewKey("int64"), int64(1), int64(0), new(int64)},
{NewKey("uint16"), uint16(1), uint16(0), new(uint16)},
{NewKey("uint32"), uint32(1), uint32(0), new(uint32)},
{NewKey("uint64"), uint64(1), uint64(0), new(uint64)},
/*
{NewKey("int"), sdk.NewInt(1), *new(sdk.Int), new(sdk.Int)},
{NewKey("uint"), sdk.NewUint(1), *new(sdk.Uint), new(sdk.Uint)},
{NewKey("dec"), sdk.NewDec(1), *new(sdk.Dec), new(sdk.Dec)},
*/
}
assert.NotPanics(t, func() { s.SetString(ctx, kvs[0].key, "test") })
assert.NotPanics(t, func() { s.SetBool(ctx, kvs[1].key, true) })
assert.NotPanics(t, func() { s.SetInt16(ctx, kvs[2].key, int16(1)) })
assert.NotPanics(t, func() { s.SetInt32(ctx, kvs[3].key, int32(1)) })
assert.NotPanics(t, func() { s.SetInt64(ctx, kvs[4].key, int64(1)) })
assert.NotPanics(t, func() { s.SetUint16(ctx, kvs[5].key, uint16(1)) })
assert.NotPanics(t, func() { s.SetUint32(ctx, kvs[6].key, uint32(1)) })
assert.NotPanics(t, func() { s.SetUint64(ctx, kvs[7].key, uint64(1)) })
assert.NotPanics(t, func() { s.SetInt(ctx, kvs[8].key, sdk.NewInt(1)) })
assert.NotPanics(t, func() { s.SetUint(ctx, kvs[9].key, sdk.NewUint(1)) })
assert.NotPanics(t, func() { s.SetDec(ctx, kvs[10].key, sdk.NewDec(1)) })
for _, kv := range kvs {
require.NotPanics(t, func() { space.Set(ctx, kv.key, kv.param) })
}
var res interface{}
var err error
for _, kv := range kvs {
require.NotPanics(t, func() { space.GetIfExists(ctx, NewKey("invalid"), kv.ptr) })
require.Equal(t, kv.zero, reflect.ValueOf(kv.ptr).Elem().Interface())
require.Panics(t, func() { space.Get(ctx, NewKey("invalid"), kv.ptr) })
require.Equal(t, kv.zero, reflect.ValueOf(kv.ptr).Elem().Interface())
// String
def0 := "default"
res, err = g.GetString(ctx, kvs[0].key)
assert.Nil(t, err)
assert.Equal(t, kvs[0].param, res)
require.NotPanics(t, func() { space.GetIfExists(ctx, kv.key, kv.ptr) })
require.Equal(t, kv.param, reflect.ValueOf(kv.ptr).Elem().Interface())
require.NotPanics(t, func() { space.Get(ctx, kv.key, kv.ptr) })
require.Equal(t, kv.param, reflect.ValueOf(kv.ptr).Elem().Interface())
_, err = g.GetString(ctx, "invalid")
assert.NotNil(t, err)
res = g.GetStringWithDefault(ctx, kvs[0].key, def0)
assert.Equal(t, kvs[0].param, res)
res = g.GetStringWithDefault(ctx, "invalid", def0)
assert.Equal(t, def0, res)
// Bool
def1 := false
res, err = g.GetBool(ctx, kvs[1].key)
assert.Nil(t, err)
assert.Equal(t, kvs[1].param, res)
_, err = g.GetBool(ctx, "invalid")
assert.NotNil(t, err)
res = g.GetBoolWithDefault(ctx, kvs[1].key, def1)
assert.Equal(t, kvs[1].param, res)
res = g.GetBoolWithDefault(ctx, "invalid", def1)
assert.Equal(t, def1, res)
// Int16
def2 := int16(0)
res, err = g.GetInt16(ctx, kvs[2].key)
assert.Nil(t, err)
assert.Equal(t, kvs[2].param, res)
_, err = g.GetInt16(ctx, "invalid")
assert.NotNil(t, err)
res = g.GetInt16WithDefault(ctx, kvs[2].key, def2)
assert.Equal(t, kvs[2].param, res)
res = g.GetInt16WithDefault(ctx, "invalid", def2)
assert.Equal(t, def2, res)
// Int32
def3 := int32(0)
res, err = g.GetInt32(ctx, kvs[3].key)
assert.Nil(t, err)
assert.Equal(t, kvs[3].param, res)
_, err = g.GetInt32(ctx, "invalid")
assert.NotNil(t, err)
res = g.GetInt32WithDefault(ctx, kvs[3].key, def3)
assert.Equal(t, kvs[3].param, res)
res = g.GetInt32WithDefault(ctx, "invalid", def3)
assert.Equal(t, def3, res)
// Int64
def4 := int64(0)
res, err = g.GetInt64(ctx, kvs[4].key)
assert.Nil(t, err)
assert.Equal(t, kvs[4].param, res)
_, err = g.GetInt64(ctx, "invalid")
assert.NotNil(t, err)
res = g.GetInt64WithDefault(ctx, kvs[4].key, def4)
assert.Equal(t, kvs[4].param, res)
res = g.GetInt64WithDefault(ctx, "invalid", def4)
assert.Equal(t, def4, res)
// Uint16
def5 := uint16(0)
res, err = g.GetUint16(ctx, kvs[5].key)
assert.Nil(t, err)
assert.Equal(t, kvs[5].param, res)
_, err = g.GetUint16(ctx, "invalid")
assert.NotNil(t, err)
res = g.GetUint16WithDefault(ctx, kvs[5].key, def5)
assert.Equal(t, kvs[5].param, res)
res = g.GetUint16WithDefault(ctx, "invalid", def5)
assert.Equal(t, def5, res)
// Uint32
def6 := uint32(0)
res, err = g.GetUint32(ctx, kvs[6].key)
assert.Nil(t, err)
assert.Equal(t, kvs[6].param, res)
_, err = g.GetUint32(ctx, "invalid")
assert.NotNil(t, err)
res = g.GetUint32WithDefault(ctx, kvs[6].key, def6)
assert.Equal(t, kvs[6].param, res)
res = g.GetUint32WithDefault(ctx, "invalid", def6)
assert.Equal(t, def6, res)
// Uint64
def7 := uint64(0)
res, err = g.GetUint64(ctx, kvs[7].key)
assert.Nil(t, err)
assert.Equal(t, kvs[7].param, res)
_, err = g.GetUint64(ctx, "invalid")
assert.NotNil(t, err)
res = g.GetUint64WithDefault(ctx, kvs[7].key, def7)
assert.Equal(t, kvs[7].param, res)
res = g.GetUint64WithDefault(ctx, "invalid", def7)
assert.Equal(t, def7, res)
// Int
def8 := sdk.NewInt(0)
res, err = g.GetInt(ctx, kvs[8].key)
assert.Nil(t, err)
assert.Equal(t, kvs[8].param, res)
_, err = g.GetInt(ctx, "invalid")
assert.NotNil(t, err)
res = g.GetIntWithDefault(ctx, kvs[8].key, def8)
assert.Equal(t, kvs[8].param, res)
res = g.GetIntWithDefault(ctx, "invalid", def8)
assert.Equal(t, def8, res)
// Uint
def9 := sdk.NewUint(0)
res, err = g.GetUint(ctx, kvs[9].key)
assert.Nil(t, err)
assert.Equal(t, kvs[9].param, res)
_, err = g.GetUint(ctx, "invalid")
assert.NotNil(t, err)
res = g.GetUintWithDefault(ctx, kvs[9].key, def9)
assert.Equal(t, kvs[9].param, res)
res = g.GetUintWithDefault(ctx, "invalid", def9)
assert.Equal(t, def9, res)
// Rat
def10 := sdk.NewDec(0)
res, err = g.GetDec(ctx, kvs[10].key)
assert.Nil(t, err)
assert.Equal(t, kvs[10].param, res)
_, err = g.GetDec(ctx, "invalid")
assert.NotNil(t, err)
res = g.GetDecWithDefault(ctx, kvs[10].key, def10)
assert.Equal(t, kvs[10].param, res)
res = g.GetDecWithDefault(ctx, "invalid", def10)
assert.Equal(t, def10, res)
require.Panics(t, func() { space.Get(ctx, NewKey("invalid"), kv.ptr) })
require.Equal(t, kv.param, reflect.ValueOf(kv.ptr).Elem().Interface())
require.Panics(t, func() { space.Get(ctx, kv.key, nil) })
require.Panics(t, func() { space.Get(ctx, kv.key, new(s)) })
}
}

View File

@ -1,37 +0,0 @@
package params
import (
sdk "github.com/cosmos/cosmos-sdk/types"
)
// GenesisState defines initial activated msg types
type GenesisState struct {
ActivatedTypes []string `json:"activated-types"`
}
// ActivatedParamKey - paramstore key for msg type activation
func ActivatedParamKey(ty string) string {
return "Activated/" + ty
}
// InitGenesis stores activated type to param store
// nolint: errcheck
func InitGenesis(ctx sdk.Context, k Keeper, data GenesisState) {
for _, ty := range data.ActivatedTypes {
k.set(ctx, ActivatedParamKey(ty), true)
}
}
// NewAnteHandler returns an AnteHandler that checks
// whether msg type is activate or not
func NewAnteHandler(k Keeper) sdk.AnteHandler {
return func(ctx sdk.Context, tx sdk.Tx, simulate bool) (sdk.Context, sdk.Result, bool) {
for _, msg := range tx.GetMsgs() {
ok := k.Getter().GetBoolWithDefault(ctx, ActivatedParamKey(msg.Type()), false)
if !ok {
return ctx, sdk.ErrUnauthorized("deactivated msg type").Result(), true
}
}
return ctx, sdk.Result{}, false
}
}

22
x/params/space.go Normal file
View File

@ -0,0 +1,22 @@
package params
import (
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/x/params/space"
)
// nolint - reexport
type Space = space.Space
type ReadOnlySpace = space.ReadOnlySpace
type Key = space.Key
type KeyFieldPair = space.KeyFieldPair
type KeyFieldPairs = space.KeyFieldPairs
type ParamStruct = space.ParamStruct
// nolint - reexport
func NewKey(keys ...string) Key {
return space.NewKey(keys...)
}
func UnmarshalParamsFromMap(m map[string][]byte, cdc *codec.Codec, ps space.ParamStruct) error {
return space.UnmarshalParamsFromMap(m, cdc, ps)
}

72
x/params/space/key.go Normal file
View File

@ -0,0 +1,72 @@
package space
import (
tmlibs "github.com/tendermint/tendermint/libs/common"
"github.com/cosmos/cosmos-sdk/codec"
)
// Wrapper for key string
type Key struct {
s string
}
// Appending two keys with '/' as separator
// Checks alpanumericity
func (k Key) Append(keys ...string) (res Key) {
res = k
for _, key := range keys {
if !tmlibs.IsASCIIText(key) {
panic("parameter key expressions can only contain alphanumeric characters")
}
res.s = res.s + "/" + key
}
return
}
// NewKey constructs a key from a list of strings
func NewKey(keys ...string) (res Key) {
if len(keys) < 1 {
panic("length of parameter keys must not be zero")
}
res = Key{keys[0]}
return res.Append(keys[1:]...)
}
// KeyBytes make KVStore key bytes from Key
func (k Key) Bytes() []byte {
return []byte(k.s)
}
// Human readable string
func (k Key) String() string {
return k.s
}
// Used for associating paramstore key and field of param structs
type KeyFieldPair struct {
Key Key
Field interface{}
}
// Slice of KeyFieldPair
type KeyFieldPairs []KeyFieldPair
// Interface for structs containing parameters for a module
type ParamStruct interface {
KeyFieldPairs() KeyFieldPairs
}
// Takes a map from key string to byte slice and
// unmarshalles it to ParamStruct
func UnmarshalParamsFromMap(m map[string][]byte, cdc *codec.Codec, ps ParamStruct) error {
for _, p := range ps.KeyFieldPairs() {
err := cdc.UnmarshalJSON(m[p.Key.String()], p.Field)
if err != nil {
return err
}
}
return nil
}

145
x/params/space/space.go Normal file
View File

@ -0,0 +1,145 @@
package space
import (
"fmt"
"reflect"
tmlibs "github.com/tendermint/tendermint/libs/common"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
)
// Individual parameter store for each keeper
type Space struct {
cdc *codec.Codec
key sdk.StoreKey
tkey sdk.StoreKey
space []byte
}
// NewSpace constructs a store with namespace
func NewSpace(cdc *codec.Codec, key sdk.StoreKey, tkey sdk.StoreKey, space string) Space {
if !tmlibs.IsASCIIText(space) {
panic("paramstore space expressions can only contain alphanumeric characters")
}
return Space{
cdc: cdc,
key: key,
tkey: tkey,
space: []byte(space + "/"),
}
}
// Get parameter from store
func (s Space) Get(ctx sdk.Context, key Key, ptr interface{}) {
store := ctx.KVStore(s.key).Prefix(s.space)
bz := store.Get(key.Bytes())
err := s.cdc.UnmarshalJSON(bz, ptr)
if err != nil {
panic(err)
}
}
// GetIfExists do not modify ptr if the stored parameter is nil
func (s Space) GetIfExists(ctx sdk.Context, key Key, ptr interface{}) {
store := ctx.KVStore(s.key).Prefix(s.space)
bz := store.Get(key.Bytes())
if bz == nil {
return
}
err := s.cdc.UnmarshalJSON(bz, ptr)
if err != nil {
panic(err)
}
}
// Get raw bytes of parameter from store
func (s Space) GetRaw(ctx sdk.Context, key Key) []byte {
store := ctx.KVStore(s.key).Prefix(s.space)
res := store.Get(key.Bytes())
return res
}
// Check if the parameter is set in the store
func (s Space) Has(ctx sdk.Context, key Key) bool {
store := ctx.KVStore(s.key).Prefix(s.space)
return store.Has(key.Bytes())
}
// Returns true if the parameter is set in the block
func (s Space) Modified(ctx sdk.Context, key Key) bool {
tstore := ctx.KVStore(s.tkey).Prefix(s.space)
return tstore.Has(key.Bytes())
}
// Set parameter, return error if stored parameter has different type from input
func (s Space) Set(ctx sdk.Context, key Key, param interface{}) error {
store := ctx.KVStore(s.key).Prefix(s.space)
keybz := key.Bytes()
bz := store.Get(keybz)
if bz != nil {
ptrty := reflect.PtrTo(reflect.TypeOf(param))
ptr := reflect.New(ptrty).Interface()
if s.cdc.UnmarshalJSON(bz, ptr) != nil {
return fmt.Errorf("Type mismatch with stored param and provided param")
}
}
bz, err := s.cdc.MarshalJSON(param)
if err != nil {
return err
}
store.Set(keybz, bz)
tstore := ctx.KVStore(s.tkey).Prefix(s.space)
tstore.Set(keybz, []byte{})
return nil
}
// Set raw bytes of parameter
func (s Space) SetRaw(ctx sdk.Context, key Key, param []byte) {
keybz := key.Bytes()
store := ctx.KVStore(s.key).Prefix(s.space)
store.Set(keybz, param)
tstore := ctx.KVStore(s.tkey).Prefix(s.space)
tstore.Set(keybz, []byte{})
}
// Returns a KVStore identical with the paramspace
func (s Space) KVStore(ctx sdk.Context) sdk.KVStore {
return ctx.KVStore(s.key).Prefix(s.space)
}
// Wrapper of Space, provides immutable functions only
type ReadOnlySpace struct {
s Space
}
// Exposes Get
func (ros ReadOnlySpace) Get(ctx sdk.Context, key Key, ptr interface{}) {
ros.s.Get(ctx, key, ptr)
}
// Exposes GetRaw
func (ros ReadOnlySpace) GetRaw(ctx sdk.Context, key Key) []byte {
return ros.s.GetRaw(ctx, key)
}
// Exposes Has
func (ros ReadOnlySpace) Has(ctx sdk.Context, key Key) bool {
return ros.s.Has(ctx, key)
}
// Exposes Modified
func (ros ReadOnlySpace) Modified(ctx sdk.Context, key Key) bool {
return ros.s.Modified(ctx, key)
}

View File

@ -0,0 +1,40 @@
package space
import (
"os"
"testing"
"github.com/stretchr/testify/require"
abci "github.com/tendermint/tendermint/abci/types"
dbm "github.com/tendermint/tendermint/libs/db"
"github.com/tendermint/tendermint/libs/log"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/store"
sdk "github.com/cosmos/cosmos-sdk/types"
)
// Keys for parameter access
const (
TestParamSpace = "ParamsTest"
)
// Returns components for testing
func DefaultTestComponents(t *testing.T) (sdk.Context, Space, func() sdk.CommitID) {
cdc := codec.New()
key := sdk.NewKVStoreKey("params")
tkey := sdk.NewTransientStoreKey("tparams")
db := dbm.NewMemDB()
ms := store.NewCommitMultiStore(db)
ms.WithTracer(os.Stdout)
ms.WithTracingContext(sdk.TraceContext{})
ms.MountStoreWithDB(key, sdk.StoreTypeIAVL, db)
ms.MountStoreWithDB(tkey, sdk.StoreTypeTransient, db)
err := ms.LoadLatestVersion()
require.Nil(t, err)
ctx := sdk.NewContext(ms, abci.Header{}, false, log.NewTMLogger(os.Stdout))
store := NewSpace(cdc, key, tkey, TestParamSpace)
return ctx, store, ms.Commit
}

View File

@ -28,18 +28,20 @@ func getMockApp(t *testing.T) (*mock.App, stake.Keeper, Keeper) {
keyStake := sdk.NewKVStoreKey("stake")
tkeyStake := sdk.NewTransientStoreKey("transient_stake")
keySlashing := sdk.NewKVStoreKey("slashing")
keyParams := sdk.NewKVStoreKey("params")
tkeyParams := sdk.NewTransientStoreKey("transient_params")
bankKeeper := bank.NewBaseKeeper(mapp.AccountMapper)
paramsKeeper := params.NewKeeper(mapp.Cdc, keyParams)
stakeKeeper := stake.NewKeeper(mapp.Cdc, keyStake, tkeyStake, bankKeeper, mapp.RegisterCodespace(stake.DefaultCodespace))
stakeKeeper := stake.NewKeeper(mapp.Cdc, keyStake, tkeyStake, bankKeeper, paramstore, mapp.RegisterCodespace(stake.DefaultCodespace))
keeper := NewKeeper(mapp.Cdc, keySlashing, stakeKeeper, paramstore, mapp.RegisterCodespace(DefaultCodespace))
keeper := NewKeeper(mapp.Cdc, keySlashing, stakeKeeper, paramsKeeper.Getter(), mapp.RegisterCodespace(DefaultCodespace))
mapp.Router().AddRoute("stake", stake.NewHandler(stakeKeeper))
mapp.Router().AddRoute("slashing", NewHandler(keeper))
mapp.SetEndBlocker(getEndBlocker(stakeKeeper))
mapp.SetInitChainer(getInitChainer(mapp, stakeKeeper))
require.NoError(t, mapp.CompleteSetup(keyStake, keySlashing, keyParams, tkeyStake))
require.NoError(t, mapp.CompleteSetup(keyStake, tkeyStake, keySlashing, keyParams, tkeyParams))
return mapp, stakeKeeper, keeper
}

View File

@ -5,10 +5,32 @@ import (
"github.com/cosmos/cosmos-sdk/x/stake/types"
)
// InitGenesis initializes the keeper's address to pubkey map.
func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) {
for _, validator := range data.Validators {
keeper.addPubkey(ctx, validator.GetConsPubKey())
}
return
// GenesisState - all slashing state that must be provided at genesis
type GenesisState struct {
Params Params
}
// HubDefaultGenesisState - default GenesisState used by Cosmos Hub
func HubDefaultGenesisState() GenesisState {
return GenesisState{
Params: HubDefaultParams(),
}
}
// InitGenesis initialize default parameters
// and the keeper's address to pubkey map
func InitGenesis(ctx sdk.Context, keeper Keeper, data GenesisState, sdata types.GenesisState) error {
for _, validator := range sdata.Validators {
keeper.addPubkey(ctx, validator.GetPubKey())
}
p := data.Params
keeper.paramstore.Set(ctx, maxEvidenceAgeKey, p.MaxEvidenceAge)
keeper.paramstore.Set(ctx, signedBlocksWindowKey, p.SignedBlocksWindow)
keeper.paramstore.Set(ctx, minSignedPerWindowKey, p.MinSignedPerWindow)
keeper.paramstore.Set(ctx, doubleSignUnbondDurationKey, p.DoubleSignUnbondDuration)
keeper.paramstore.Set(ctx, downtimeUnbondDurationKey, p.DowntimeUnbondDuration)
keeper.paramstore.Set(ctx, slashFractionDoubleSignKey, p.SlashFractionDoubleSign)
keeper.paramstore.Set(ctx, slashFractionDowntimeKey, p.SlashFractionDowntime)
return nil
}

View File

@ -12,7 +12,7 @@ import (
func TestCannotUnjailUnlessJailed(t *testing.T) {
// initial setup
ctx, ck, sk, _, keeper := createTestInput(t)
ctx, ck, sk, _, keeper := createTestInput(t, HubDefaultParams())
slh := NewHandler(keeper)
amtInt := int64(100)
addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt)
@ -30,7 +30,7 @@ func TestCannotUnjailUnlessJailed(t *testing.T) {
}
func TestJailedValidatorDelegations(t *testing.T) {
ctx, _, stakeKeeper, _, slashingKeeper := createTestInput(t)
ctx, _, stakeKeeper, _, slashingKeeper := createTestInput(t, HubDefaultParams())
stakeParams := stakeKeeper.GetParams(ctx)
stakeParams.UnbondingTime = 0

View File

@ -9,7 +9,7 @@ import (
)
func TestHookOnValidatorBonded(t *testing.T) {
ctx, _, _, _, keeper := createTestInput(t)
ctx, _, _, _, keeper := createTestInput(t, HubDefaultParams())
addr := sdk.ConsAddress(addrs[0])
keeper.onValidatorBonded(ctx, addr)
period := keeper.getValidatorSlashingPeriodForHeight(ctx, addr, ctx.BlockHeight())
@ -17,7 +17,7 @@ func TestHookOnValidatorBonded(t *testing.T) {
}
func TestHookOnValidatorBeginUnbonding(t *testing.T) {
ctx, _, _, _, keeper := createTestInput(t)
ctx, _, _, _, keeper := createTestInput(t, HubDefaultParams())
addr := sdk.ConsAddress(addrs[0])
keeper.onValidatorBonded(ctx, addr)
keeper.onValidatorBeginUnbonding(ctx, addr)

View File

@ -18,18 +18,19 @@ type Keeper struct {
storeKey sdk.StoreKey
cdc *codec.Codec
validatorSet sdk.ValidatorSet
params params.Getter
paramstore params.Space
// codespace
codespace sdk.CodespaceType
}
// NewKeeper creates a slashing keeper
func NewKeeper(cdc *codec.Codec, key sdk.StoreKey, vs sdk.ValidatorSet, params params.Getter, codespace sdk.CodespaceType) Keeper {
func NewKeeper(cdc *codec.Codec, key sdk.StoreKey, vs sdk.ValidatorSet, paramstore params.Space, codespace sdk.CodespaceType) Keeper {
keeper := Keeper{
storeKey: key,
cdc: cdc,
validatorSet: vs,
params: params,
paramstore: paramstore,
codespace: codespace,
}
return keeper

View File

@ -12,10 +12,12 @@ import (
// Have to change these parameters for tests
// lest the tests take forever
func init() {
defaultSignedBlocksWindow = 1000
defaultDowntimeUnbondDuration = 60 * 60
defaultDoubleSignUnbondDuration = 60 * 60
func keeperTestParams() Params {
params := HubDefaultParams()
params.SignedBlocksWindow = 1000
params.DowntimeUnbondDuration = 60 * 60
params.DoubleSignUnbondDuration = 60 * 60
return params
}
// ______________________________________________________________
@ -26,7 +28,7 @@ func init() {
func TestHandleDoubleSign(t *testing.T) {
// initial setup
ctx, ck, sk, _, keeper := createTestInput(t)
ctx, ck, sk, _, keeper := createTestInput(t, keeperTestParams())
sk = sk.WithHooks(keeper.Hooks())
amtInt := int64(100)
addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt)
@ -68,7 +70,7 @@ func TestHandleDoubleSign(t *testing.T) {
func TestSlashingPeriodCap(t *testing.T) {
// initial setup
ctx, ck, sk, _, keeper := createTestInput(t)
ctx, ck, sk, _, keeper := createTestInput(t, HubDefaultParams())
sk = sk.WithHooks(keeper.Hooks())
amtInt := int64(100)
addr, amt := addrs[0], sdk.NewInt(amtInt)
@ -133,7 +135,7 @@ func TestSlashingPeriodCap(t *testing.T) {
func TestHandleAbsentValidator(t *testing.T) {
// initial setup
ctx, ck, sk, _, keeper := createTestInput(t)
ctx, ck, sk, _, keeper := createTestInput(t, keeperTestParams())
sk = sk.WithHooks(keeper.Hooks())
amtInt := int64(100)
addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt)
@ -259,7 +261,7 @@ func TestHandleAbsentValidator(t *testing.T) {
// and that they are not immediately jailed
func TestHandleNewValidator(t *testing.T) {
// initial setup
ctx, ck, sk, _, keeper := createTestInput(t)
ctx, ck, sk, _, keeper := createTestInput(t, keeperTestParams())
addr, val, amt := addrs[0], pks[0], int64(100)
sh := stake.NewHandler(sk)
got := sh(ctx, newTestMsgCreateValidator(addr, val, sdk.NewInt(amt)))
@ -296,7 +298,7 @@ func TestHandleNewValidator(t *testing.T) {
func TestHandleAlreadyJailed(t *testing.T) {
// initial setup
ctx, _, sk, _, keeper := createTestInput(t)
ctx, _, sk, _, keeper := createTestInput(t, HubDefaultParams())
amtInt := int64(100)
addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt)
sh := stake.NewHandler(sk)

View File

@ -4,77 +4,111 @@ import (
"time"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/params"
)
// nolint
// Default parameter namespace
const (
MaxEvidenceAgeKey = "slashing/MaxEvidenceAge"
SignedBlocksWindowKey = "slashing/SignedBlocksWindow"
MinSignedPerWindowKey = "slashing/MinSignedPerWindow"
DoubleSignUnbondDurationKey = "slashing/DoubleSignUnbondDuration"
DowntimeUnbondDurationKey = "slashing/DowntimeUnbondDuration"
SlashFractionDoubleSignKey = "slashing/SlashFractionDoubleSign"
SlashFractionDowntimeKey = "slashing/SlashFractionDowntime"
DefaultParamSpace = "slashing"
)
// nolint - Key generators for parameter access
func MaxEvidenceAgeKey() params.Key { return params.NewKey("MaxEvidenceAge") }
func SignedBlocksWindowKey() params.Key { return params.NewKey("SignedBlocksWindow") }
func MinSignedPerWindowKey() params.Key { return params.NewKey("MinSignedPerWindow") }
func DoubleSignUnbondDurationKey() params.Key { return params.NewKey("DoubleSignUnbondDuration") }
func DowntimeUnbondDurationKey() params.Key { return params.NewKey("DowntimeUnbondDuration") }
func SlashFractionDoubleSignKey() params.Key { return params.NewKey("SlashFractionDoubleSign") }
func SlashFractionDowntimeKey() params.Key { return params.NewKey("SlashFractionDowntime") }
// Cached parameter keys
var (
maxEvidenceAgeKey = MaxEvidenceAgeKey()
signedBlocksWindowKey = SignedBlocksWindowKey()
minSignedPerWindowKey = MinSignedPerWindowKey()
doubleSignUnbondDurationKey = DoubleSignUnbondDurationKey()
downtimeUnbondDurationKey = DowntimeUnbondDurationKey()
slashFractionDoubleSignKey = SlashFractionDoubleSignKey()
slashFractionDowntimeKey = SlashFractionDowntimeKey()
)
// Params - used for initializing default parameter for slashing at genesis
type Params struct {
MaxEvidenceAge time.Duration `json:"max-evidence-age"`
SignedBlocksWindow int64 `json:"signed-blocks-window"`
MinSignedPerWindow sdk.Dec `json:"min-signed-per-window"`
DoubleSignUnbondDuration time.Duration `json:"doublesign-unbond-duration"`
DowntimeUnbondDuration time.Duration `json:"downtime-unbond-duration"`
SlashFractionDoubleSign sdk.Dec `json:"slash-fraction-doublesign"`
SlashFractionDowntime sdk.Dec `json:"slash-fraction-downtime"`
}
// Default parameters used by Cosmos Hub
func HubDefaultParams() Params {
return Params{
// defaultMaxEvidenceAge = 60 * 60 * 24 * 7 * 3
// TODO Temporarily set to 2 minutes for testnets.
MaxEvidenceAge: 60 * 2 * time.Second,
// TODO Temporarily set to five minutes for testnets
DoubleSignUnbondDuration: 60 * 5 * time.Second,
// TODO Temporarily set to 100 blocks for testnets
SignedBlocksWindow: 100,
// TODO Temporarily set to 10 minutes for testnets
DowntimeUnbondDuration: 60 * 10 * time.Second,
MinSignedPerWindow: sdk.NewDecWithPrec(5, 1),
SlashFractionDoubleSign: sdk.NewDec(1).Quo(sdk.NewDec(20)),
SlashFractionDowntime: sdk.NewDec(1).Quo(sdk.NewDec(100)),
}
}
// MaxEvidenceAge - Max age for evidence - 21 days (3 weeks)
// MaxEvidenceAge = 60 * 60 * 24 * 7 * 3
func (k Keeper) MaxEvidenceAge(ctx sdk.Context) time.Duration {
return time.Duration(k.params.GetInt64WithDefault(ctx, MaxEvidenceAgeKey, defaultMaxEvidenceAge)) * time.Second
func (k Keeper) MaxEvidenceAge(ctx sdk.Context) (res time.Duration) {
k.paramstore.Get(ctx, maxEvidenceAgeKey, &res)
return
}
// SignedBlocksWindow - sliding window for downtime slashing
func (k Keeper) SignedBlocksWindow(ctx sdk.Context) int64 {
return k.params.GetInt64WithDefault(ctx, SignedBlocksWindowKey, defaultSignedBlocksWindow)
func (k Keeper) SignedBlocksWindow(ctx sdk.Context) (res int64) {
k.paramstore.Get(ctx, signedBlocksWindowKey, &res)
return
}
// Downtime slashing thershold - default 50%
// Downtime slashing thershold - default 50% of the SignedBlocksWindow
func (k Keeper) MinSignedPerWindow(ctx sdk.Context) int64 {
minSignedPerWindow := k.params.GetDecWithDefault(ctx, MinSignedPerWindowKey, defaultMinSignedPerWindow)
var minSignedPerWindow sdk.Dec
k.paramstore.Get(ctx, minSignedPerWindowKey, &minSignedPerWindow)
signedBlocksWindow := k.SignedBlocksWindow(ctx)
return sdk.NewDec(signedBlocksWindow).Mul(minSignedPerWindow).RoundInt64()
}
// Double-sign unbond duration
func (k Keeper) DoubleSignUnbondDuration(ctx sdk.Context) time.Duration {
return time.Duration(k.params.GetInt64WithDefault(ctx, DoubleSignUnbondDurationKey, defaultDoubleSignUnbondDuration)) * time.Second
func (k Keeper) DoubleSignUnbondDuration(ctx sdk.Context) (res time.Duration) {
k.paramstore.Get(ctx, doubleSignUnbondDurationKey, &res)
return
}
// Downtime unbond duration
func (k Keeper) DowntimeUnbondDuration(ctx sdk.Context) time.Duration {
return time.Duration(k.params.GetInt64WithDefault(ctx, DowntimeUnbondDurationKey, defaultDowntimeUnbondDuration)) * time.Second
func (k Keeper) DowntimeUnbondDuration(ctx sdk.Context) (res time.Duration) {
k.paramstore.Get(ctx, downtimeUnbondDurationKey, &res)
return
}
// SlashFractionDoubleSign - currently default 5%
func (k Keeper) SlashFractionDoubleSign(ctx sdk.Context) sdk.Dec {
return k.params.GetDecWithDefault(ctx, SlashFractionDoubleSignKey, defaultSlashFractionDoubleSign)
func (k Keeper) SlashFractionDoubleSign(ctx sdk.Context) (res sdk.Dec) {
k.paramstore.Get(ctx, slashFractionDoubleSignKey, &res)
return
}
// SlashFractionDowntime - currently default 1%
func (k Keeper) SlashFractionDowntime(ctx sdk.Context) sdk.Dec {
return k.params.GetDecWithDefault(ctx, SlashFractionDowntimeKey, defaultSlashFractionDowntime)
func (k Keeper) SlashFractionDowntime(ctx sdk.Context) (res sdk.Dec) {
k.paramstore.Get(ctx, slashFractionDowntimeKey, &res)
return
}
// declared as var because of keeper_test.go
// TODO: make it const or parameter of NewKeeper
var (
// defaultMaxEvidenceAge = 60 * 60 * 24 * 7 * 3
// TODO Temporarily set to 2 minutes for testnets.
defaultMaxEvidenceAge int64 = 60 * 2
// TODO Temporarily set to five minutes for testnets
defaultDoubleSignUnbondDuration int64 = 60 * 5
// TODO Temporarily set to 10000 blocks for testnets
defaultSignedBlocksWindow int64 = 10000
// TODO Temporarily set to 10 minutes for testnets
defaultDowntimeUnbondDuration int64 = 60 * 10
defaultMinSignedPerWindow = sdk.NewDecWithPrec(5, 1)
defaultSlashFractionDoubleSign = sdk.NewDec(1).Quo(sdk.NewDec(20))
defaultSlashFractionDowntime = sdk.NewDec(1).Quo(sdk.NewDec(100))
)

View File

@ -10,7 +10,7 @@ import (
)
func TestGetSetValidatorSigningInfo(t *testing.T) {
ctx, _, _, _, keeper := createTestInput(t)
ctx, _, _, _, keeper := createTestInput(t, HubDefaultParams())
info, found := keeper.getValidatorSigningInfo(ctx, sdk.ConsAddress(addrs[0]))
require.False(t, found)
newInfo := ValidatorSigningInfo{
@ -29,7 +29,7 @@ func TestGetSetValidatorSigningInfo(t *testing.T) {
}
func TestGetSetValidatorSigningBitArray(t *testing.T) {
ctx, _, _, _, keeper := createTestInput(t)
ctx, _, _, _, keeper := createTestInput(t, HubDefaultParams())
signed := keeper.getValidatorSigningBitArray(ctx, sdk.ConsAddress(addrs[0]), 0)
require.False(t, signed) // treat empty key as unsigned
keeper.setValidatorSigningBitArray(ctx, sdk.ConsAddress(addrs[0]), 0, true)

View File

@ -9,7 +9,7 @@ import (
)
func TestGetSetValidatorSlashingPeriod(t *testing.T) {
ctx, _, _, _, keeper := createTestInput(t)
ctx, _, _, _, keeper := createTestInput(t, HubDefaultParams())
addr := sdk.ConsAddress(addrs[0])
height := int64(5)
require.Panics(t, func() { keeper.getValidatorSlashingPeriodForHeight(ctx, addr, height) })
@ -60,7 +60,7 @@ func TestGetSetValidatorSlashingPeriod(t *testing.T) {
}
func TestValidatorSlashingPeriodCap(t *testing.T) {
ctx, _, _, _, keeper := createTestInput(t)
ctx, _, _, _, keeper := createTestInput(t, HubDefaultParams())
addr := sdk.ConsAddress(addrs[0])
height := int64(5)
newPeriod := ValidatorSlashingPeriod{

View File

@ -49,12 +49,13 @@ func createTestCodec() *codec.Codec {
return cdc
}
func createTestInput(t *testing.T) (sdk.Context, bank.Keeper, stake.Keeper, params.Setter, Keeper) {
func createTestInput(t *testing.T, defaults Params) (sdk.Context, bank.Keeper, stake.Keeper, params.Space, Keeper) {
keyAcc := sdk.NewKVStoreKey("acc")
keyStake := sdk.NewKVStoreKey("stake")
tkeyStake := sdk.NewTransientStoreKey("transient_stake")
keySlashing := sdk.NewKVStoreKey("slashing")
keyParams := sdk.NewKVStoreKey("params")
tkeyParams := sdk.NewTransientStoreKey("transient_params")
db := dbm.NewMemDB()
ms := store.NewCommitMultiStore(db)
ms.MountStoreWithDB(keyAcc, sdk.StoreTypeIAVL, db)
@ -62,14 +63,16 @@ func createTestInput(t *testing.T) (sdk.Context, bank.Keeper, stake.Keeper, para
ms.MountStoreWithDB(keyStake, sdk.StoreTypeIAVL, db)
ms.MountStoreWithDB(keySlashing, sdk.StoreTypeIAVL, db)
ms.MountStoreWithDB(keyParams, sdk.StoreTypeIAVL, db)
ms.MountStoreWithDB(tkeyParams, sdk.StoreTypeTransient, db)
err := ms.LoadLatestVersion()
require.Nil(t, err)
ctx := sdk.NewContext(ms, abci.Header{Time: time.Unix(0, 0)}, false, log.NewTMLogger(os.Stdout))
cdc := createTestCodec()
accountMapper := auth.NewAccountMapper(cdc, keyAcc, auth.ProtoBaseAccount)
ck := bank.NewBaseKeeper(accountMapper)
params := params.NewKeeper(cdc, keyParams)
sk := stake.NewKeeper(cdc, keyStake, tkeyStake, ck, stake.DefaultCodespace)
paramstore := params.NewKeeper(cdc, keyParams, tkeyParams).Subspace(DefaultParamSpace)
sk := stake.NewKeeper(cdc, keyStake, tkeyStake, ck, paramstore, stake.DefaultCodespace)
genesis := stake.DefaultGenesisState()
genesis.Pool.LooseTokens = sdk.NewDec(initCoins.MulRaw(int64(len(addrs))).Int64())
@ -83,8 +86,12 @@ func createTestInput(t *testing.T) (sdk.Context, bank.Keeper, stake.Keeper, para
})
}
require.Nil(t, err)
keeper := NewKeeper(cdc, keySlashing, sk, params.Getter(), DefaultCodespace)
return ctx, ck, sk, params.Setter(), keeper
keeper := NewKeeper(cdc, keySlashing, sk, paramstore, DefaultCodespace)
err = InitGenesis(ctx, keeper, GenesisState{defaults}, genesis)
require.Nil(t, err)
return ctx, ck, sk, paramstore, keeper
}
func newPubKey(pk string) (res crypto.PubKey) {

View File

@ -13,7 +13,7 @@ import (
)
func TestBeginBlocker(t *testing.T) {
ctx, ck, sk, _, keeper := createTestInput(t)
ctx, ck, sk, _, keeper := createTestInput(t, HubDefaultParams())
addr, pk, amt := addrs[2], pks[2], sdk.NewInt(100)
// bond the validator

View File

@ -7,6 +7,7 @@ import (
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/bank"
"github.com/cosmos/cosmos-sdk/x/mock"
"github.com/cosmos/cosmos-sdk/x/params"
"github.com/stretchr/testify/require"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/crypto/ed25519"
@ -36,15 +37,20 @@ func getMockApp(t *testing.T) (*mock.App, Keeper) {
RegisterCodec(mApp.Cdc)
keyStake := sdk.NewKVStoreKey("stake")
tkeyStake := sdk.NewTransientStoreKey("transient_stake")
keyParams := sdk.NewKVStoreKey("params")
tkeyParams := sdk.NewTransientStoreKey("transient_params")
bankKeeper := bank.NewBaseKeeper(mApp.AccountMapper)
keeper := NewKeeper(mApp.Cdc, keyStake, tkeyStake, bankKeeper, mApp.RegisterCodespace(DefaultCodespace))
pk := params.NewKeeper(mApp.Cdc, keyParams, tkeyParams)
keeper := NewKeeper(mApp.Cdc, keyStake, tkeyStake, coinKeeper, pk.Subspace("stake"), mApp.RegisterCodespace(DefaultCodespace))
mApp.Router().AddRoute("stake", NewHandler(keeper))
mApp.SetEndBlocker(getEndBlocker(keeper))
mApp.SetInitChainer(getInitChainer(mApp, keeper))
require.NoError(t, mApp.CompleteSetup(keyStake, tkeyStake))
require.NoError(t, mApp.CompleteSetup(keyStake, tkeyStake, keyParams, tkeyParams))
return mApp, keeper
}

View File

@ -10,6 +10,7 @@ import (
"github.com/cosmos/cosmos-sdk/client/context"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
paramutils "github.com/cosmos/cosmos-sdk/x/params/client/utils"
"github.com/cosmos/cosmos-sdk/x/stake"
"github.com/cosmos/cosmos-sdk/x/stake/types"
)
@ -464,16 +465,14 @@ func GetCmdQueryParams(storeName string, cdc *codec.Codec) *cobra.Command {
Short: "Query the current staking parameters information",
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
key := stake.ParamKey
cliCtx := context.NewCLIContext().WithCodec(cdc)
res, err := cliCtx.QueryStore(key, storeName)
var params types.Params
err := paramutils.QueryParams(cliCtx, storeName, &params)
if err != nil {
return err
}
params := types.MustUnmarshalParams(cdc, res)
switch viper.Get(cli.OutputFlag) {
case "text":
human := params.HumanReadableString()

View File

@ -335,7 +335,7 @@ func (k Keeper) unbond(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValA
//______________________________________________________________________________________________________
// get info for begin functions: MinTime and CreationHeight
func (k Keeper) getBeginInfo(ctx sdk.Context, params types.Params, valSrcAddr sdk.ValAddress) (
func (k Keeper) getBeginInfo(ctx sdk.Context, valSrcAddr sdk.ValAddress) (
minTime time.Time, height int64, completeNow bool) {
validator, found := k.GetValidator(ctx, valSrcAddr)
@ -343,7 +343,7 @@ func (k Keeper) getBeginInfo(ctx sdk.Context, params types.Params, valSrcAddr sd
case !found || validator.Status == sdk.Bonded:
// the longest wait - just unbonding period from now
minTime = ctx.BlockHeader().Time.Add(params.UnbondingTime)
minTime = ctx.BlockHeader().Time.Add(k.UnbondingTime(ctx))
height = ctx.BlockHeader().Height
return minTime, height, false
@ -376,9 +376,8 @@ func (k Keeper) BeginUnbonding(ctx sdk.Context,
}
// create the unbonding delegation
params := k.GetParams(ctx)
minTime, height, completeNow := k.getBeginInfo(ctx, params, valAddr)
balance := sdk.NewCoin(params.BondDenom, returnAmount.RoundInt())
minTime, height, completeNow := k.getBeginInfo(ctx, valAddr)
balance := sdk.Coin{k.BondDenom(ctx), returnAmount.RoundInt()}
// no need to create the ubd object just complete now
if completeNow {
@ -437,8 +436,7 @@ func (k Keeper) BeginRedelegation(ctx sdk.Context, delAddr sdk.AccAddress,
return err
}
params := k.GetParams(ctx)
returnCoin := sdk.NewCoin(params.BondDenom, returnAmount.RoundInt())
returnCoin := sdk.Coin{k.BondDenom(ctx), returnAmount.RoundInt()}
dstValidator, found := k.GetValidator(ctx, valDstAddr)
if !found {
return types.ErrBadRedelegationDst(k.Codespace())
@ -449,7 +447,7 @@ func (k Keeper) BeginRedelegation(ctx sdk.Context, delAddr sdk.AccAddress,
}
// create the unbonding delegation
minTime, height, completeNow := k.getBeginInfo(ctx, params, valSrcAddr)
minTime, height, completeNow := k.getBeginInfo(ctx, valSrcAddr)
if completeNow { // no need to create the redelegation object
return nil

View File

@ -5,6 +5,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/bank"
"github.com/cosmos/cosmos-sdk/x/params"
"github.com/cosmos/cosmos-sdk/x/stake/types"
)
@ -15,17 +16,19 @@ type Keeper struct {
cdc *codec.Codec
bankKeeper bank.Keeper
hooks sdk.StakingHooks
paramstore params.Space
// codespace
codespace sdk.CodespaceType
}
func NewKeeper(cdc *codec.Codec, key, tkey sdk.StoreKey, ck bank.Keeper, codespace sdk.CodespaceType) Keeper {
func NewKeeper(cdc *codec.Codec, key, tkey sdk.StoreKey, ck bank.Keeper, paramstore params.Space, codespace sdk.CodespaceType) Keeper {
keeper := Keeper{
storeKey: key,
storeTKey: tkey,
cdc: cdc,
bankKeeper: ck,
paramstore: paramstore,
hooks: nil,
codespace: codespace,
}
@ -48,29 +51,6 @@ func (k Keeper) Codespace() sdk.CodespaceType {
return k.codespace
}
//_________________________________________________________________________
// some generic reads/writes that don't need their own files
// load/save the global staking params
func (k Keeper) GetParams(ctx sdk.Context) (params types.Params) {
store := ctx.KVStore(k.storeKey)
b := store.Get(ParamKey)
if b == nil {
panic("Stored params should not have been nil")
}
k.cdc.MustUnmarshalBinary(b, &params)
return
}
// set the params
func (k Keeper) SetParams(ctx sdk.Context, params types.Params) {
store := ctx.KVStore(k.storeKey)
b := k.cdc.MustMarshalBinary(params)
store.Set(ParamKey, b)
}
//_______________________________________________________________________
// load/save the pool

View File

@ -12,7 +12,8 @@ import (
//nolint
var (
// Keys for store prefixes
ParamKey = []byte{0x00} // key for parameters relating to staking
// TODO DEPRECATED: delete in next release and reorder keys
// ParamKey = []byte{0x00} // key for parameters relating to staking
PoolKey = []byte{0x01} // key for the staking pools
ValidatorsKey = []byte{0x02} // prefix for each key to a validator
ValidatorsByConsAddrKey = []byte{0x03} // prefix for each key to a validator index, by pubkey

100
x/stake/keeper/params.go Normal file
View File

@ -0,0 +1,100 @@
package keeper
import (
"time"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/stake/types"
)
// Default parameter namespace
const (
DefaultParamSpace = "stake"
)
// Cached parameter keys
var (
keyInflationRateChange = types.KeyInflationRateChange()
keyInflationMax = types.KeyInflationMax()
keyInflationMin = types.KeyInflationMin()
keyGoalBonded = types.KeyGoalBonded()
keyUnbondingTime = types.KeyUnbondingTime()
keyMaxValidators = types.KeyMaxValidators()
keyBondDenom = types.KeyBondDenom()
)
// InflationRateChange - Maximum annual change in inflation rate
func (k Keeper) InflationRateChange(ctx sdk.Context) (res sdk.Dec) {
k.paramstore.Get(ctx, keyInflationRateChange, &res)
return
}
// InflationMax - Maximum inflation rate
func (k Keeper) InflationMax(ctx sdk.Context) (res sdk.Dec) {
k.paramstore.Get(ctx, keyInflationMax, &res)
return
}
// InflationMin - Minimum inflation rate
func (k Keeper) InflationMin(ctx sdk.Context) (res sdk.Dec) {
k.paramstore.Get(ctx, keyInflationMin, &res)
return
}
// GoalBonded - Goal of percent bonded atoms
func (k Keeper) GoalBonded(ctx sdk.Context) (res sdk.Dec) {
k.paramstore.Get(ctx, keyGoalBonded, &res)
return
}
// UnbondingTime
func (k Keeper) UnbondingTime(ctx sdk.Context) (res time.Duration) {
k.paramstore.Get(ctx, keyUnbondingTime, &res)
return
}
// MaxValidators - Maximum number of validators
func (k Keeper) MaxValidators(ctx sdk.Context) (res uint16) {
k.paramstore.Get(ctx, keyMaxValidators, &res)
return
}
// BondDenom - Bondable coin denomination
func (k Keeper) BondDenom(ctx sdk.Context) (res string) {
k.paramstore.Get(ctx, keyBondDenom, &res)
return
}
// Get all parameteras as types.Params
func (k Keeper) GetParams(ctx sdk.Context) (res types.Params) {
res.InflationRateChange = k.InflationRateChange(ctx)
res.InflationMax = k.InflationMax(ctx)
res.InflationMin = k.InflationMin(ctx)
res.GoalBonded = k.GoalBonded(ctx)
res.UnbondingTime = k.UnbondingTime(ctx)
res.MaxValidators = k.MaxValidators(ctx)
res.BondDenom = k.BondDenom(ctx)
return
}
// Need a distinct function because setParams depends on an existing previous
// record of params to exist (to check if maxValidators has changed) - and we
// panic on retrieval if it doesn't exist - hence if we use setParams for the very
// first params set it will panic.
func (k Keeper) SetParams(ctx sdk.Context, params types.Params) {
if k.MaxValidators(ctx) != params.MaxValidators {
k.UpdateBondedValidatorsFull(ctx)
}
k.SetNewParams(ctx, params)
}
// set the params without updating validator set
func (k Keeper) SetNewParams(ctx sdk.Context, params types.Params) {
k.paramstore.Set(ctx, keyInflationRateChange, params.InflationRateChange)
k.paramstore.Set(ctx, keyInflationMax, params.InflationMax)
k.paramstore.Set(ctx, keyInflationMin, params.InflationMin)
k.paramstore.Set(ctx, keyGoalBonded, params.GoalBonded)
k.paramstore.Set(ctx, keyUnbondingTime, params.UnbondingTime)
k.paramstore.Set(ctx, keyMaxValidators, params.MaxValidators)
k.paramstore.Set(ctx, keyBondDenom, params.BondDenom)
}

View File

@ -19,6 +19,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/bank"
"github.com/cosmos/cosmos-sdk/x/params"
"github.com/cosmos/cosmos-sdk/x/stake/types"
)
@ -92,12 +93,16 @@ func CreateTestInput(t *testing.T, isCheckTx bool, initCoins int64) (sdk.Context
keyStake := sdk.NewKVStoreKey("stake")
tkeyStake := sdk.NewTransientStoreKey("transient_stake")
keyAcc := sdk.NewKVStoreKey("acc")
keyParams := sdk.NewKVStoreKey("params")
tkeyParams := sdk.NewTransientStoreKey("transient_params")
db := dbm.NewMemDB()
ms := store.NewCommitMultiStore(db)
ms.MountStoreWithDB(tkeyStake, sdk.StoreTypeTransient, nil)
ms.MountStoreWithDB(keyStake, sdk.StoreTypeIAVL, db)
ms.MountStoreWithDB(keyAcc, sdk.StoreTypeIAVL, db)
ms.MountStoreWithDB(keyParams, sdk.StoreTypeIAVL, db)
ms.MountStoreWithDB(tkeyParams, sdk.StoreTypeTransient, db)
err := ms.LoadLatestVersion()
require.Nil(t, err)
@ -108,8 +113,11 @@ func CreateTestInput(t *testing.T, isCheckTx bool, initCoins int64) (sdk.Context
keyAcc, // target store
auth.ProtoBaseAccount, // prototype
)
ck := bank.NewBaseKeeper(accountMapper)
keeper := NewKeeper(cdc, keyStake, tkeyStake, ck, types.DefaultCodespace)
pk := params.NewKeeper(cdc, keyParams, tkeyParams)
keeper := NewKeeper(cdc, keyStake, tkeyStake, ck, pk.Subspace("stake"), types.DefaultCodespace)
keeper.SetPool(ctx, types.InitialPool())
keeper.SetParams(ctx, types.DefaultParams())
keeper.InitIntraTxCounter(ctx)
@ -118,7 +126,7 @@ func CreateTestInput(t *testing.T, isCheckTx bool, initCoins int64) (sdk.Context
for _, addr := range Addrs {
pool := keeper.GetPool(ctx)
_, _, err := ck.AddCoins(ctx, addr, sdk.Coins{
{keeper.GetParams(ctx).BondDenom, sdk.NewInt(initCoins)},
{keeper.BondDenom(ctx), sdk.NewInt(initCoins)},
})
require.Nil(t, err)
pool.LooseTokens = pool.LooseTokens.Add(sdk.NewDec(initCoins))

View File

@ -238,7 +238,7 @@ func (k Keeper) GetValidatorsBonded(ctx sdk.Context) (validators []types.Validat
store := ctx.KVStore(k.storeKey)
// add the actual validator power sorted store
maxValidators := k.GetParams(ctx).MaxValidators
maxValidators := k.MaxValidators(ctx)
validators = make([]types.Validator, maxValidators)
iterator := sdk.KVStorePrefixIterator(store, ValidatorsBondedIndexKey)
@ -263,7 +263,7 @@ func (k Keeper) GetValidatorsBonded(ctx sdk.Context) (validators []types.Validat
// get the group of bonded validators sorted by power-rank
func (k Keeper) GetBondedValidatorsByPower(ctx sdk.Context) []types.Validator {
store := ctx.KVStore(k.storeKey)
maxValidators := k.GetParams(ctx).MaxValidators
maxValidators := k.MaxValidators(ctx)
validators := make([]types.Validator, maxValidators)
iterator := sdk.KVStoreReversePrefixIterator(store, ValidatorsByPowerIndexKey)

View File

@ -11,6 +11,7 @@ import (
"github.com/cosmos/cosmos-sdk/x/bank"
"github.com/cosmos/cosmos-sdk/x/mock"
"github.com/cosmos/cosmos-sdk/x/mock/simulation"
"github.com/cosmos/cosmos-sdk/x/params"
"github.com/cosmos/cosmos-sdk/x/stake"
)
@ -23,7 +24,11 @@ func TestStakeWithRandomMessages(t *testing.T) {
bankKeeper := bank.NewBaseKeeper(mapper)
stakeKey := sdk.NewKVStoreKey("stake")
stakeTKey := sdk.NewTransientStoreKey("transient_stake")
stakeKeeper := stake.NewKeeper(mapp.Cdc, stakeKey, stakeTKey, bankKeeper, stake.DefaultCodespace)
paramsKey := sdk.NewKVStoreKey("params")
paramsTKey := sdk.NewTransientStoreKey("transient_params")
paramstore := params.NewKeeper(mapp.Cdc, paramsKey, paramsTKey).Subspace(stake.DefaultParamSpace)
stakeKeeper := stake.NewKeeper(mapp.Cdc, stakeKey, stakeTKey, bankKeeper, paramstore, stake.DefaultCodespace)
mapp.Router().AddRoute("stake", stake.NewHandler(stakeKeeper))
mapp.SetEndBlocker(func(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock {
validatorUpdates := stake.EndBlocker(ctx, stakeKeeper)
@ -32,7 +37,7 @@ func TestStakeWithRandomMessages(t *testing.T) {
}
})
err := mapp.CompleteSetup(stakeKey, stakeTKey)
err := mapp.CompleteSetup(stakeKey, stakeTKey, paramsKey, paramsTKey)
if err != nil {
panic(err)
}

View File

@ -40,7 +40,6 @@ var (
GetValidatorsByPowerIndexKey = keeper.GetValidatorsByPowerIndexKey
GetDelegationKey = keeper.GetDelegationKey
GetDelegationsKey = keeper.GetDelegationsKey
ParamKey = keeper.ParamKey
PoolKey = keeper.PoolKey
ValidatorsKey = keeper.ValidatorsKey
ValidatorsByConsAddrKey = keeper.ValidatorsByConsAddrKey
@ -60,6 +59,14 @@ var (
GetREDsToValDstIndexKey = keeper.GetREDsToValDstIndexKey
GetREDsByDelToValDstIndexKey = keeper.GetREDsByDelToValDstIndexKey
DefaultParamSpace = keeper.DefaultParamSpace
KeyInflationRateChange = types.KeyInflationRateChange
KeyInflationMax = types.KeyInflationMax
KeyGoalBonded = types.KeyGoalBonded
KeyUnbondingTime = types.KeyUnbondingTime
KeyMaxValidators = types.KeyMaxValidators
KeyBondDenom = types.KeyBondDenom
DefaultParams = types.DefaultParams
InitialPool = types.InitialPool
NewValidator = types.NewValidator

View File

@ -7,12 +7,22 @@ import (
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/params"
)
// defaultUnbondingTime reflects three weeks in seconds as the default
// unbonding time.
const defaultUnbondingTime time.Duration = 60 * 60 * 24 * 3 * time.Second
// nolint - Key generators for parameter access
func KeyInflationRateChange() params.Key { return params.NewKey("InflationRateChange") }
func KeyInflationMax() params.Key { return params.NewKey("InflationMax") }
func KeyInflationMin() params.Key { return params.NewKey("InflationMin") }
func KeyGoalBonded() params.Key { return params.NewKey("GoalBonded") }
func KeyUnbondingTime() params.Key { return params.NewKey("UnbondingTime") }
func KeyMaxValidators() params.Key { return params.NewKey("MaxValidators") }
func KeyBondDenom() params.Key { return params.NewKey("BondDenom") }
// Params defines the high level settings for staking
type Params struct {
InflationRateChange sdk.Dec `json:"inflation_rate_change"` // maximum annual change in inflation rate
@ -26,6 +36,19 @@ type Params struct {
BondDenom string `json:"bond_denom"` // bondable coin denomination
}
// Implements params.ParamStruct
func (p *Params) KeyFieldPairs() params.KeyFieldPairs {
return params.KeyFieldPairs{
{KeyInflationRateChange(), &p.InflationRateChange},
{KeyInflationMax(), &p.InflationMax},
{KeyInflationMin(), &p.InflationMin},
{KeyGoalBonded(), &p.GoalBonded},
{KeyUnbondingTime(), &p.UnbondingTime},
{KeyMaxValidators(), &p.MaxValidators},
{KeyBondDenom(), &p.BondDenom},
}
}
// Equal returns a boolean determining if two Param types are identical.
func (p Params) Equal(p2 Params) bool {
bz1 := MsgCdc.MustMarshalBinary(&p)