Merge branch 'master' into release/v0.21.1
This commit is contained in:
commit
12fa42b43b
|
@ -32,6 +32,8 @@ BUG FIXES
|
|||
* [keys] \#1629 - updating password no longer asks for a new password when the first entered password was incorrect
|
||||
* [lcd] importing an account would create a random account
|
||||
* [server] 'gaiad init' command family now writes provided name as the moniker in `config.toml`
|
||||
* [build] Added Ledger build support via `LEDGER_ENABLED=true|false`
|
||||
* True by default except when cross-compiling
|
||||
|
||||
## 0.20.0
|
||||
|
||||
|
|
|
@ -10,11 +10,6 @@
|
|||
# name = "github.com/user/project"
|
||||
# version = "1.0.0"
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project2"
|
||||
# branch = "dev"
|
||||
# source = "github.com/myfork/project2"
|
||||
#
|
||||
# [[override]]
|
||||
# name = "github.com/x/y"
|
||||
# version = "2.4.0"
|
||||
|
@ -66,7 +61,7 @@
|
|||
|
||||
[[constraint]]
|
||||
name = "github.com/bartekn/go-bip39"
|
||||
branch = "master"
|
||||
revision = "a05967ea095d81c8fe4833776774cfaff8e5036c"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/zondax/ledger-goclient"
|
||||
|
|
2
Makefile
2
Makefile
|
@ -119,6 +119,8 @@ test_lint:
|
|||
gometalinter.v2 --config=tools/gometalinter.json ./...
|
||||
!(gometalinter.v2 --disable-all --enable='errcheck' --vendor ./... | grep -v "client/")
|
||||
find . -name '*.go' -type f -not -path "./vendor*" -not -path "*.git*" | xargs gofmt -d -s
|
||||
dep status >> /dev/null
|
||||
!(grep -n branch Gopkg.toml)
|
||||
|
||||
format:
|
||||
find . -name '*.go' -type f -not -path "./vendor*" -not -path "*.git*" | xargs gofmt -w -s
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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().
|
||||
|
|
|
@ -153,6 +153,9 @@ func (pkl PrivKeyLedgerSecp256k1) pubkeyLedgerSecp256k1() (pub tmcrypto.PubKey,
|
|||
|
||||
// re-serialize in the 33-byte compressed format
|
||||
cmp, err := secp256k1.ParsePubKey(key[:], secp256k1.S256())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error parsing public key: %v", err)
|
||||
}
|
||||
copy(pk[:], cmp.SerializeCompressed())
|
||||
|
||||
return pk, nil
|
||||
|
|
|
@ -158,7 +158,7 @@ func GetCmdVote(cdc *wire.Codec) *cobra.Command {
|
|||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("Vote[Voter:%s,ProposalID:%d,Option:%s]", bechVoter, msg.ProposalID, msg.Option)
|
||||
fmt.Printf("Vote[Voter:%s,ProposalID:%d,Option:%s]", bechVoter, msg.ProposalID, msg.Option.String())
|
||||
|
||||
// build and sign the transaction, then broadcast to Tendermint
|
||||
ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc))
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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, ¶m)
|
||||
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, ¶m)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, kv.param, param)
|
||||
}
|
||||
|
||||
for _, kv := range kvs {
|
||||
var param bool
|
||||
err := setter.Get(ctx, kv.key, ¶m)
|
||||
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)
|
||||
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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))
|
||||
)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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{{
|
||||
|
|
Loading…
Reference in New Issue