Merge PR #1265: Global Paramstore

in progress
in progress
stake and slashing now params
fix gaia
fix gaia again
add msg type deactivation
delete local error
in progress
revert actual application in baseapp/gaia/stake
add test, fix apps
fix MinSignedPerWindow, pass lint
fix gaia
fix keeper_test
fit with multiple msgs
fix
apply requests
pass lint
really the last fix
fix dependency
fix keeper_test
fix lint
This commit is contained in:
Joon 2018-07-13 17:12:23 -07:00 committed by Christopher Goes
parent 06216c1fdb
commit bdccbeff9e
13 changed files with 855 additions and 77 deletions

View File

@ -18,6 +18,7 @@ import (
"github.com/cosmos/cosmos-sdk/x/bank"
"github.com/cosmos/cosmos-sdk/x/gov"
"github.com/cosmos/cosmos-sdk/x/ibc"
"github.com/cosmos/cosmos-sdk/x/params"
"github.com/cosmos/cosmos-sdk/x/slashing"
"github.com/cosmos/cosmos-sdk/x/stake"
)
@ -45,6 +46,7 @@ type GaiaApp struct {
keySlashing *sdk.KVStoreKey
keyGov *sdk.KVStoreKey
keyFeeCollection *sdk.KVStoreKey
keyParams *sdk.KVStoreKey
// Manage getting and setting accounts
accountMapper auth.AccountMapper
@ -54,6 +56,7 @@ type GaiaApp struct {
stakeKeeper stake.Keeper
slashingKeeper slashing.Keeper
govKeeper gov.Keeper
paramsKeeper params.Keeper
}
// NewGaiaApp returns a reference to an initialized GaiaApp.
@ -73,6 +76,7 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio
keySlashing: sdk.NewKVStoreKey("slashing"),
keyGov: sdk.NewKVStoreKey("gov"),
keyFeeCollection: sdk.NewKVStoreKey("fee"),
keyParams: sdk.NewKVStoreKey("params"),
}
// define the accountMapper
@ -85,10 +89,11 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio
// add handlers
app.coinKeeper = bank.NewKeeper(app.accountMapper)
app.ibcMapper = ibc.NewMapper(app.cdc, app.keyIBC, app.RegisterCodespace(ibc.DefaultCodespace))
app.paramsKeeper = params.NewKeeper(app.cdc, app.keyParams)
app.stakeKeeper = stake.NewKeeper(app.cdc, app.keyStake, app.coinKeeper, app.RegisterCodespace(stake.DefaultCodespace))
app.slashingKeeper = slashing.NewKeeper(app.cdc, app.keySlashing, app.stakeKeeper, app.RegisterCodespace(slashing.DefaultCodespace))
app.govKeeper = gov.NewKeeper(app.cdc, app.keyGov, app.coinKeeper, app.stakeKeeper, app.RegisterCodespace(gov.DefaultCodespace))
app.feeCollectionKeeper = auth.NewFeeCollectionKeeper(app.cdc, app.keyFeeCollection)
app.slashingKeeper = slashing.NewKeeper(app.cdc, app.keySlashing, app.stakeKeeper, app.paramsKeeper.Getter(), app.RegisterCodespace(slashing.DefaultCodespace))
// register message routes
app.Router().
@ -103,7 +108,7 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio
app.SetBeginBlocker(app.BeginBlocker)
app.SetEndBlocker(app.EndBlocker)
app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper, app.feeCollectionKeeper))
app.MountStoresIAVL(app.keyMain, app.keyAccount, app.keyIBC, app.keyStake, app.keySlashing, app.keyGov, app.keyFeeCollection)
app.MountStoresIAVL(app.keyMain, app.keyAccount, app.keyIBC, app.keyStake, app.keySlashing, app.keyGov, app.keyFeeCollection, app.keyParams)
err := app.LoadLatestVersion(app.keyMain)
if err != nil {
cmn.Exit(err.Error())

View File

@ -24,6 +24,7 @@ import (
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/bank"
"github.com/cosmos/cosmos-sdk/x/ibc"
"github.com/cosmos/cosmos-sdk/x/params"
"github.com/cosmos/cosmos-sdk/x/slashing"
"github.com/cosmos/cosmos-sdk/x/stake"
@ -133,6 +134,7 @@ type GaiaApp struct {
keyIBC *sdk.KVStoreKey
keyStake *sdk.KVStoreKey
keySlashing *sdk.KVStoreKey
keyParams *sdk.KVStoreKey
// Manage getting and setting accounts
accountMapper auth.AccountMapper
@ -141,6 +143,7 @@ type GaiaApp struct {
ibcMapper ibc.Mapper
stakeKeeper stake.Keeper
slashingKeeper slashing.Keeper
paramsKeeper params.Keeper
}
func NewGaiaApp(logger log.Logger, db dbm.DB, baseAppOptions ...func(*bam.BaseApp)) *GaiaApp {
@ -158,6 +161,7 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, baseAppOptions ...func(*bam.BaseAp
keyIBC: sdk.NewKVStoreKey("ibc"),
keyStake: sdk.NewKVStoreKey("stake"),
keySlashing: sdk.NewKVStoreKey("slashing"),
keyParams: sdk.NewKVStoreKey("params"),
}
// define the accountMapper
@ -170,8 +174,9 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, baseAppOptions ...func(*bam.BaseAp
// add handlers
app.coinKeeper = bank.NewKeeper(app.accountMapper)
app.ibcMapper = ibc.NewMapper(app.cdc, app.keyIBC, app.RegisterCodespace(ibc.DefaultCodespace))
app.paramsKeeper = params.NewKeeper(app.cdc, app.keyParams)
app.stakeKeeper = stake.NewKeeper(app.cdc, app.keyStake, app.coinKeeper, app.RegisterCodespace(stake.DefaultCodespace))
app.slashingKeeper = slashing.NewKeeper(app.cdc, app.keySlashing, app.stakeKeeper, app.RegisterCodespace(slashing.DefaultCodespace))
app.slashingKeeper = slashing.NewKeeper(app.cdc, app.keySlashing, app.stakeKeeper, app.paramsKeeper.Getter(), app.RegisterCodespace(slashing.DefaultCodespace))
// register message routes
app.Router().

405
x/params/keeper.go Normal file
View File

@ -0,0 +1,405 @@
package params
import (
"fmt"
"reflect"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/wire"
)
// Keeper manages global parameter store
type Keeper struct {
cdc *wire.Codec
key sdk.StoreKey
}
// NewKeeper constructs a new Keeper
func NewKeeper(cdc *wire.Codec, key sdk.StoreKey) Keeper {
return Keeper{
cdc: cdc,
key: key,
}
}
// InitKeeper constructs a new Keeper with initial parameters
func InitKeeper(ctx sdk.Context, cdc *wire.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])
}
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")
}
}
bz, err := k.cdc.MarshalBinary(param)
if err != nil {
return err
}
store.Set([]byte(key), bz)
return nil
}
// 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)
}
// 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
}
// GetRat is helper function for rat params
func (k Getter) GetRat(ctx sdk.Context, key string) (res sdk.Rat, 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
}
// GetRatWithDefault is helper function for sdk.Rat params with default value
func (k Getter) GetRatWithDefault(ctx sdk.Context, key string, def sdk.Rat) (res sdk.Rat) {
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)
}
}
// SetRat is helper function for rat params
func (k Setter) SetRat(ctx sdk.Context, key string, param sdk.Rat) {
if err := k.k.set(ctx, key, param); err != nil {
panic(err)
}
}

280
x/params/keeper_test.go Normal file
View File

@ -0,0 +1,280 @@
package params
import (
"testing"
"github.com/stretchr/testify/assert"
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/store"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/wire"
)
func defaultContext(key sdk.StoreKey) sdk.Context {
db := dbm.NewMemDB()
cms := store.NewCommitMultiStore(db)
cms.MountStoreWithDB(key, sdk.StoreTypeIAVL, db)
cms.LoadLatestVersion()
ctx := sdk.NewContext(cms, abci.Header{}, false, log.NewNopLogger())
return ctx
}
func TestKeeper(t *testing.T) {
kvs := []struct {
key string
param int64
}{
{"key1", 10},
{"key2", 55},
{"key3", 182},
{"key4", 17582},
{"key5", 2768554},
}
skey := sdk.NewKVStoreKey("test")
ctx := defaultContext(skey)
setter := NewKeeper(wire.NewCodec(), skey).Setter()
for _, kv := range kvs {
err := setter.Set(ctx, kv.key, kv.param)
assert.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)
}
cdc := wire.NewCodec()
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)
}
for _, kv := range kvs {
var param bool
err := setter.Get(ctx, kv.key, &param)
assert.NotNil(t, err)
}
for _, kv := range kvs {
err := setter.Set(ctx, kv.key, true)
assert.NotNil(t, err)
}
}
func TestGetter(t *testing.T) {
key := sdk.NewKVStoreKey("test")
ctx := defaultContext(key)
keeper := NewKeeper(wire.NewCodec(), key)
g := keeper.Getter()
s := keeper.Setter()
kvs := []struct {
key string
param 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.NewRat(1)},
}
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.SetRat(ctx, kvs[10].key, sdk.NewRat(1)) })
var res interface{}
var err error
// String
def0 := "default"
res, err = g.GetString(ctx, kvs[0].key)
assert.Nil(t, err)
assert.Equal(t, kvs[0].param, res)
_, 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.NewRat(0)
res, err = g.GetRat(ctx, kvs[10].key)
assert.Nil(t, err)
assert.Equal(t, kvs[10].param, res)
_, err = g.GetRat(ctx, "invalid")
assert.NotNil(t, err)
res = g.GetRatWithDefault(ctx, kvs[10].key, def10)
assert.Equal(t, kvs[10].param, res)
res = g.GetRatWithDefault(ctx, "invalid", def10)
assert.Equal(t, def10, res)
}

36
x/params/msg_status.go Normal file
View File

@ -0,0 +1,36 @@
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
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) (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
}
}

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/cosmos/cosmos-sdk/x/stake"
"github.com/stretchr/testify/require"
abci "github.com/tendermint/tendermint/abci/types"
@ -26,15 +27,18 @@ func getMockApp(t *testing.T) (*mock.App, stake.Keeper, Keeper) {
RegisterWire(mapp.Cdc)
keyStake := sdk.NewKVStoreKey("stake")
keySlashing := sdk.NewKVStoreKey("slashing")
keyParams := sdk.NewKVStoreKey("params")
coinKeeper := bank.NewKeeper(mapp.AccountMapper)
paramsKeeper := params.NewKeeper(mapp.Cdc, keyParams)
stakeKeeper := stake.NewKeeper(mapp.Cdc, keyStake, coinKeeper, mapp.RegisterCodespace(stake.DefaultCodespace))
keeper := NewKeeper(mapp.Cdc, keySlashing, stakeKeeper, 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([]*sdk.KVStoreKey{keyStake, keySlashing}))
require.NoError(t, mapp.CompleteSetup([]*sdk.KVStoreKey{keyStake, keySlashing, keyParams}))
return mapp, stakeKeeper, keeper
}

View File

@ -11,7 +11,7 @@ import (
func TestCannotUnrevokeUnlessRevoked(t *testing.T) {
// initial setup
ctx, ck, sk, keeper := createTestInput(t)
ctx, ck, sk, _, keeper := createTestInput(t)
slh := NewHandler(keeper)
amtInt := int64(100)
addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt)

View File

@ -5,6 +5,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/wire"
"github.com/cosmos/cosmos-sdk/x/params"
"github.com/tendermint/tendermint/crypto"
)
@ -13,17 +14,19 @@ type Keeper struct {
storeKey sdk.StoreKey
cdc *wire.Codec
validatorSet sdk.ValidatorSet
params params.Getter
// codespace
codespace sdk.CodespaceType
}
// NewKeeper creates a slashing keeper
func NewKeeper(cdc *wire.Codec, key sdk.StoreKey, vs sdk.ValidatorSet, codespace sdk.CodespaceType) Keeper {
func NewKeeper(cdc *wire.Codec, key sdk.StoreKey, vs sdk.ValidatorSet, params params.Getter, codespace sdk.CodespaceType) Keeper {
keeper := Keeper{
storeKey: key,
cdc: cdc,
validatorSet: vs,
params: params,
codespace: codespace,
}
return keeper
@ -37,16 +40,17 @@ func (k Keeper) handleDoubleSign(ctx sdk.Context, pubkey crypto.PubKey, infracti
address := sdk.ValAddress(pubkey.Address())
// Double sign too old
if age > MaxEvidenceAge {
logger.Info(fmt.Sprintf("Ignored double sign from %s at height %d, age of %d past max age of %d", pubkey.Address(), infractionHeight, age, MaxEvidenceAge))
maxEvidenceAge := k.MaxEvidenceAge(ctx)
if age > maxEvidenceAge {
logger.Info(fmt.Sprintf("Ignored double sign from %s at height %d, age of %d past max age of %d", pubkey.Address(), infractionHeight, age, maxEvidenceAge))
return
}
// Double sign confirmed
logger.Info(fmt.Sprintf("Confirmed double sign from %s at height %d, age of %d less than max age of %d", pubkey.Address(), infractionHeight, age, MaxEvidenceAge))
logger.Info(fmt.Sprintf("Confirmed double sign from %s at height %d, age of %d less than max age of %d", pubkey.Address(), infractionHeight, age, maxEvidenceAge))
// Slash validator
k.validatorSet.Slash(ctx, pubkey, infractionHeight, power, SlashFractionDoubleSign)
k.validatorSet.Slash(ctx, pubkey, infractionHeight, power, k.SlashFractionDoubleSign(ctx))
// Revoke validator
k.validatorSet.Revoke(ctx, pubkey)
@ -56,7 +60,7 @@ func (k Keeper) handleDoubleSign(ctx sdk.Context, pubkey crypto.PubKey, infracti
if !found {
panic(fmt.Sprintf("Expected signing info for validator %s but not found", address))
}
signInfo.JailedUntil = time + DoubleSignUnbondDuration
signInfo.JailedUntil = time + k.DoubleSignUnbondDuration(ctx)
k.setValidatorSigningInfo(ctx, address, signInfo)
}
@ -73,7 +77,7 @@ func (k Keeper) handleValidatorSignature(ctx sdk.Context, pubkey crypto.PubKey,
// If this validator has never been seen before, construct a new SigningInfo with the correct start height
signInfo = NewValidatorSigningInfo(height, 0, 0, 0)
}
index := signInfo.IndexOffset % SignedBlocksWindow
index := signInfo.IndexOffset % k.SignedBlocksWindow(ctx)
signInfo.IndexOffset++
// Update signed block bit array & counter
@ -93,15 +97,15 @@ func (k Keeper) handleValidatorSignature(ctx sdk.Context, pubkey crypto.PubKey,
}
if !signed {
logger.Info(fmt.Sprintf("Absent validator %s at height %d, %d signed, threshold %d", pubkey.Address(), height, signInfo.SignedBlocksCounter, MinSignedPerWindow))
logger.Info(fmt.Sprintf("Absent validator %s at height %d, %d signed, threshold %d", pubkey.Address(), height, signInfo.SignedBlocksCounter, k.MinSignedPerWindow(ctx)))
}
minHeight := signInfo.StartHeight + SignedBlocksWindow
if height > minHeight && signInfo.SignedBlocksCounter < MinSignedPerWindow {
minHeight := signInfo.StartHeight + k.SignedBlocksWindow(ctx)
if height > minHeight && signInfo.SignedBlocksCounter < k.MinSignedPerWindow(ctx) {
// Downtime confirmed, slash, revoke, and jail the validator
logger.Info(fmt.Sprintf("Validator %s past min height of %d and below signed blocks threshold of %d", pubkey.Address(), minHeight, MinSignedPerWindow))
k.validatorSet.Slash(ctx, pubkey, height, power, SlashFractionDowntime)
logger.Info(fmt.Sprintf("Validator %s past min height of %d and below signed blocks threshold of %d", pubkey.Address(), minHeight, k.MinSignedPerWindow(ctx)))
k.validatorSet.Slash(ctx, pubkey, height, power, k.SlashFractionDowntime(ctx))
k.validatorSet.Revoke(ctx, pubkey)
signInfo.JailedUntil = ctx.BlockHeader().Time + DowntimeUnbondDuration
signInfo.JailedUntil = ctx.BlockHeader().Time + k.DowntimeUnbondDuration(ctx)
}
// Set the updated signing info

View File

@ -14,10 +14,9 @@ import (
// Have to change these parameters for tests
// lest the tests take forever
func init() {
SignedBlocksWindow = 1000
MinSignedPerWindow = SignedBlocksWindow / 2
DowntimeUnbondDuration = 60 * 60
DoubleSignUnbondDuration = 60 * 60
defaultSignedBlocksWindow = 1000
defaultDowntimeUnbondDuration = 60 * 60
defaultDoubleSignUnbondDuration = 60 * 60
}
// Test that a validator is slashed correctly
@ -25,7 +24,7 @@ func init() {
func TestHandleDoubleSign(t *testing.T) {
// initial setup
ctx, ck, sk, keeper := createTestInput(t)
ctx, ck, sk, _, keeper := createTestInput(t)
amtInt := int64(100)
addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt)
got := stake.NewHandler(sk)(ctx, newTestMsgCreateValidator(addr, val, amt))
@ -46,7 +45,7 @@ func TestHandleDoubleSign(t *testing.T) {
sk.Unrevoke(ctx, val)
// power should be reduced
require.Equal(t, sdk.NewRatFromInt(amt).Mul(sdk.NewRat(19).Quo(sdk.NewRat(20))), sk.Validator(ctx, addr).GetPower())
ctx = ctx.WithBlockHeader(abci.Header{Time: 1 + MaxEvidenceAge})
ctx = ctx.WithBlockHeader(abci.Header{Time: 1 + keeper.MaxEvidenceAge(ctx)})
// double sign past max age
keeper.handleDoubleSign(ctx, val, 0, 0, amtInt)
@ -58,7 +57,7 @@ func TestHandleDoubleSign(t *testing.T) {
func TestHandleAbsentValidator(t *testing.T) {
// initial setup
ctx, ck, sk, keeper := createTestInput(t)
ctx, ck, sk, _, keeper := createTestInput(t)
amtInt := int64(100)
addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt)
sh := stake.NewHandler(sk)
@ -77,24 +76,24 @@ func TestHandleAbsentValidator(t *testing.T) {
height := int64(0)
// 1000 first blocks OK
for ; height < SignedBlocksWindow; height++ {
for ; height < keeper.SignedBlocksWindow(ctx); height++ {
ctx = ctx.WithBlockHeight(height)
keeper.handleValidatorSignature(ctx, val, amtInt, true)
}
info, found = keeper.getValidatorSigningInfo(ctx, sdk.ValAddress(val.Address()))
require.True(t, found)
require.Equal(t, int64(0), info.StartHeight)
require.Equal(t, SignedBlocksWindow, info.SignedBlocksCounter)
require.Equal(t, keeper.SignedBlocksWindow(ctx), info.SignedBlocksCounter)
// 500 blocks missed
for ; height < SignedBlocksWindow+(SignedBlocksWindow-MinSignedPerWindow); height++ {
for ; height < keeper.SignedBlocksWindow(ctx)+(keeper.SignedBlocksWindow(ctx)-keeper.MinSignedPerWindow(ctx)); height++ {
ctx = ctx.WithBlockHeight(height)
keeper.handleValidatorSignature(ctx, val, amtInt, false)
}
info, found = keeper.getValidatorSigningInfo(ctx, sdk.ValAddress(val.Address()))
require.True(t, found)
require.Equal(t, int64(0), info.StartHeight)
require.Equal(t, SignedBlocksWindow-MinSignedPerWindow, info.SignedBlocksCounter)
require.Equal(t, keeper.SignedBlocksWindow(ctx)-keeper.MinSignedPerWindow(ctx), info.SignedBlocksCounter)
// validator should be bonded still
validator, _ := sk.GetValidatorByPubKey(ctx, val)
@ -108,7 +107,7 @@ func TestHandleAbsentValidator(t *testing.T) {
info, found = keeper.getValidatorSigningInfo(ctx, sdk.ValAddress(val.Address()))
require.True(t, found)
require.Equal(t, int64(0), info.StartHeight)
require.Equal(t, SignedBlocksWindow-MinSignedPerWindow-1, info.SignedBlocksCounter)
require.Equal(t, keeper.SignedBlocksWindow(ctx)-keeper.MinSignedPerWindow(ctx)-1, info.SignedBlocksCounter)
// validator should have been revoked
validator, _ = sk.GetValidatorByPubKey(ctx, val)
@ -119,7 +118,7 @@ func TestHandleAbsentValidator(t *testing.T) {
require.False(t, got.IsOK())
// unrevocation should succeed after jail expiration
ctx = ctx.WithBlockHeader(abci.Header{Time: DowntimeUnbondDuration + 1})
ctx = ctx.WithBlockHeader(abci.Header{Time: keeper.DowntimeUnbondDuration(ctx) + 1})
got = slh(ctx, NewMsgUnrevoke(addr))
require.True(t, got.IsOK())
@ -135,7 +134,7 @@ func TestHandleAbsentValidator(t *testing.T) {
info, found = keeper.getValidatorSigningInfo(ctx, sdk.ValAddress(val.Address()))
require.True(t, found)
require.Equal(t, height, info.StartHeight)
require.Equal(t, SignedBlocksWindow-MinSignedPerWindow-1, info.SignedBlocksCounter)
require.Equal(t, keeper.SignedBlocksWindow(ctx)-keeper.MinSignedPerWindow(ctx)-1, info.SignedBlocksCounter)
// validator should not be immediately revoked again
height++
@ -145,14 +144,14 @@ func TestHandleAbsentValidator(t *testing.T) {
require.Equal(t, sdk.Bonded, validator.GetStatus())
// 500 signed blocks
nextHeight := height + MinSignedPerWindow + 1
nextHeight := height + keeper.MinSignedPerWindow(ctx) + 1
for ; height < nextHeight; height++ {
ctx = ctx.WithBlockHeight(height)
keeper.handleValidatorSignature(ctx, val, amtInt, false)
}
// validator should be revoked again after 500 unsigned blocks
nextHeight = height + MinSignedPerWindow + 1
nextHeight = height + keeper.MinSignedPerWindow(ctx) + 1
for ; height <= nextHeight; height++ {
ctx = ctx.WithBlockHeight(height)
keeper.handleValidatorSignature(ctx, val, amtInt, false)
@ -166,7 +165,7 @@ func TestHandleAbsentValidator(t *testing.T) {
// and that they are not immediately revoked
func TestHandleNewValidator(t *testing.T) {
// initial setup
ctx, ck, sk, keeper := createTestInput(t)
ctx, ck, sk, _, keeper := createTestInput(t)
addr, val, amt := addrs[0], pks[0], int64(100)
sh := stake.NewHandler(sk)
got := sh(ctx, newTestMsgCreateValidator(addr, val, sdk.NewInt(amt)))
@ -176,16 +175,16 @@ func TestHandleNewValidator(t *testing.T) {
require.Equal(t, sdk.NewRat(amt), sk.Validator(ctx, addr).GetPower())
// 1000 first blocks not a validator
ctx = ctx.WithBlockHeight(SignedBlocksWindow + 1)
ctx = ctx.WithBlockHeight(keeper.SignedBlocksWindow(ctx) + 1)
// Now a validator, for two blocks
keeper.handleValidatorSignature(ctx, val, 100, true)
ctx = ctx.WithBlockHeight(SignedBlocksWindow + 2)
ctx = ctx.WithBlockHeight(keeper.SignedBlocksWindow(ctx) + 2)
keeper.handleValidatorSignature(ctx, val, 100, false)
info, found := keeper.getValidatorSigningInfo(ctx, sdk.ValAddress(val.Address()))
require.True(t, found)
require.Equal(t, int64(SignedBlocksWindow+1), info.StartHeight)
require.Equal(t, int64(keeper.SignedBlocksWindow(ctx)+1), info.StartHeight)
require.Equal(t, int64(2), info.IndexOffset)
require.Equal(t, int64(1), info.SignedBlocksCounter)
require.Equal(t, int64(0), info.JailedUntil)

View File

@ -4,39 +4,75 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
)
// nolint
const (
MaxEvidenceAgeKey = "slashing/MaxEvidenceAge"
SignedBlocksWindowKey = "slashing/SignedBlocksWindow"
MinSignedPerWindowKey = "slashing/MinSignedPerWindow"
DoubleSignUnbondDurationKey = "slashing/DoubleSignUnbondDuration"
DowntimeUnbondDurationKey = "slashing/DowntimeUnbondDuration"
SlashFractionDoubleSignKey = "slashing/SlashFractionDoubleSign"
SlashFractionDowntimeKey = "slashing/SlashFractionDowntime"
)
// MaxEvidenceAge - Max age for evidence - 21 days (3 weeks)
// MaxEvidenceAge = 60 * 60 * 24 * 7 * 3
func (k Keeper) MaxEvidenceAge(ctx sdk.Context) int64 {
return k.params.GetInt64WithDefault(ctx, MaxEvidenceAgeKey, defaultMaxEvidenceAge)
}
// SignedBlocksWindow - sliding window for downtime slashing
func (k Keeper) SignedBlocksWindow(ctx sdk.Context) int64 {
return k.params.GetInt64WithDefault(ctx, SignedBlocksWindowKey, defaultSignedBlocksWindow)
}
// Downtime slashing thershold - default 50%
func (k Keeper) MinSignedPerWindow(ctx sdk.Context) int64 {
minSignedPerWindow := k.params.GetRatWithDefault(ctx, MinSignedPerWindowKey, defaultMinSignedPerWindow)
signedBlocksWindow := k.SignedBlocksWindow(ctx)
return sdk.NewRat(signedBlocksWindow).Mul(minSignedPerWindow).RoundInt64()
}
// Double-sign unbond duration
func (k Keeper) DoubleSignUnbondDuration(ctx sdk.Context) int64 {
return k.params.GetInt64WithDefault(ctx, DoubleSignUnbondDurationKey, defaultDoubleSignUnbondDuration)
}
// Downtime unbond duration
func (k Keeper) DowntimeUnbondDuration(ctx sdk.Context) int64 {
return k.params.GetInt64WithDefault(ctx, DowntimeUnbondDurationKey, defaultDowntimeUnbondDuration)
}
// SlashFractionDoubleSign - currently default 5%
func (k Keeper) SlashFractionDoubleSign(ctx sdk.Context) sdk.Rat {
return k.params.GetRatWithDefault(ctx, SlashFractionDoubleSignKey, defaultSlashFractionDoubleSign)
}
// SlashFractionDowntime - currently default 1%
func (k Keeper) SlashFractionDowntime(ctx sdk.Context) sdk.Rat {
return k.params.GetRatWithDefault(ctx, SlashFractionDowntimeKey, defaultSlashFractionDowntime)
}
// declared as var because of keeper_test.go
// TODO: make it const or parameter of NewKeeper
var (
// MaxEvidenceAge - Max age for evidence - 21 days (3 weeks)
// TODO Should this be a governance parameter or just modifiable with SoftwareUpgradeProposals?
// MaxEvidenceAge = 60 * 60 * 24 * 7 * 3
// defaultMaxEvidenceAge = 60 * 60 * 24 * 7 * 3
// TODO Temporarily set to 2 minutes for testnets.
MaxEvidenceAge int64 = 60 * 2
defaultMaxEvidenceAge int64 = 60 * 2
// SignedBlocksWindow - sliding window for downtime slashing
// TODO Governance parameter?
// TODO Temporarily set to 40000 blocks for testnets
SignedBlocksWindow int64 = 40000
// Downtime slashing threshold - 50%
// TODO Governance parameter?
MinSignedPerWindow = SignedBlocksWindow / 2
// Downtime unbond duration
// TODO Governance parameter?
// TODO Temporarily set to five minutes for testnets
DowntimeUnbondDuration int64 = 60 * 5
defaultDoubleSignUnbondDuration int64 = 60 * 5
// Double-sign unbond duration
// TODO Governance parameter?
// TODO Temporarily set to five minutes for testnets
DoubleSignUnbondDuration int64 = 60 * 5
)
var (
// SlashFractionDoubleSign - currently 5%
// TODO Governance parameter?
SlashFractionDoubleSign = sdk.NewRat(1).Quo(sdk.NewRat(20))
// SlashFractionDowntime - currently 1%
// TODO Governance parameter?
SlashFractionDowntime = sdk.NewRat(1).Quo(sdk.NewRat(100))
// TODO Temporarily set to 100 blocks for testnets
defaultSignedBlocksWindow int64 = 100
// TODO Temporarily set to 10 minutes for testnets
defaultDowntimeUnbondDuration int64 = 60 * 10
defaultMinSignedPerWindow sdk.Rat = sdk.NewRat(1, 2)
defaultSlashFractionDoubleSign = sdk.NewRat(1).Quo(sdk.NewRat(20))
defaultSlashFractionDowntime = sdk.NewRat(1).Quo(sdk.NewRat(100))
)

View File

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

View File

@ -17,6 +17,7 @@ import (
"github.com/cosmos/cosmos-sdk/wire"
"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"
)
@ -46,21 +47,24 @@ func createTestCodec() *wire.Codec {
return cdc
}
func createTestInput(t *testing.T) (sdk.Context, bank.Keeper, stake.Keeper, Keeper) {
func createTestInput(t *testing.T) (sdk.Context, bank.Keeper, stake.Keeper, params.Setter, Keeper) {
keyAcc := sdk.NewKVStoreKey("acc")
keyStake := sdk.NewKVStoreKey("stake")
keySlashing := sdk.NewKVStoreKey("slashing")
keyParams := sdk.NewKVStoreKey("params")
db := dbm.NewMemDB()
ms := store.NewCommitMultiStore(db)
ms.MountStoreWithDB(keyAcc, sdk.StoreTypeIAVL, db)
ms.MountStoreWithDB(keyStake, sdk.StoreTypeIAVL, db)
ms.MountStoreWithDB(keySlashing, sdk.StoreTypeIAVL, db)
ms.MountStoreWithDB(keyParams, sdk.StoreTypeIAVL, db)
err := ms.LoadLatestVersion()
require.Nil(t, err)
ctx := sdk.NewContext(ms, abci.Header{}, false, log.NewTMLogger(os.Stdout))
cdc := createTestCodec()
accountMapper := auth.NewAccountMapper(cdc, keyAcc, auth.ProtoBaseAccount)
ck := bank.NewKeeper(accountMapper)
params := params.NewKeeper(cdc, keyParams)
sk := stake.NewKeeper(cdc, keyStake, ck, stake.DefaultCodespace)
genesis := stake.DefaultGenesisState()
@ -75,8 +79,8 @@ func createTestInput(t *testing.T) (sdk.Context, bank.Keeper, stake.Keeper, Keep
})
}
require.Nil(t, err)
keeper := NewKeeper(cdc, keySlashing, sk, DefaultCodespace)
return ctx, ck, sk, keeper
keeper := NewKeeper(cdc, keySlashing, sk, params.Getter(), DefaultCodespace)
return ctx, ck, sk, params.Setter(), 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)
addr, pk, amt := addrs[2], pks[2], sdk.NewInt(100)
// bond the validator
@ -47,7 +47,7 @@ func TestBeginBlocker(t *testing.T) {
height := int64(0)
// for 1000 blocks, mark the validator as having signed
for ; height < SignedBlocksWindow; height++ {
for ; height < keeper.SignedBlocksWindow(ctx); height++ {
ctx = ctx.WithBlockHeight(height)
req = abci.RequestBeginBlock{
Validators: []abci.SigningValidator{{
@ -59,7 +59,7 @@ func TestBeginBlocker(t *testing.T) {
}
// for 500 blocks, mark the validator as having not signed
for ; height < ((SignedBlocksWindow * 2) - MinSignedPerWindow + 1); height++ {
for ; height < ((keeper.SignedBlocksWindow(ctx) * 2) - keeper.MinSignedPerWindow(ctx) + 1); height++ {
ctx = ctx.WithBlockHeight(height)
req = abci.RequestBeginBlock{
Validators: []abci.SigningValidator{{