Merge pull request #1105 from cosmos/cwgoes/slashing-v1.1

Fix minor slashing issues
This commit is contained in:
Christopher Goes 2018-06-01 18:41:13 +02:00 committed by GitHub
commit 537ce91e33
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 126 additions and 10 deletions

View File

@ -14,6 +14,7 @@ import (
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli" authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
bankcmd "github.com/cosmos/cosmos-sdk/x/bank/client/cli" bankcmd "github.com/cosmos/cosmos-sdk/x/bank/client/cli"
ibccmd "github.com/cosmos/cosmos-sdk/x/ibc/client/cli" ibccmd "github.com/cosmos/cosmos-sdk/x/ibc/client/cli"
slashingcmd "github.com/cosmos/cosmos-sdk/x/slashing/client/cli"
stakecmd "github.com/cosmos/cosmos-sdk/x/stake/client/cli" stakecmd "github.com/cosmos/cosmos-sdk/x/stake/client/cli"
"github.com/cosmos/cosmos-sdk/cmd/gaia/app" "github.com/cosmos/cosmos-sdk/cmd/gaia/app"
@ -86,6 +87,7 @@ func main() {
stakecmd.GetCmdQueryValidators("stake", cdc), stakecmd.GetCmdQueryValidators("stake", cdc),
stakecmd.GetCmdQueryDelegation("stake", cdc), stakecmd.GetCmdQueryDelegation("stake", cdc),
stakecmd.GetCmdQueryDelegations("stake", cdc), stakecmd.GetCmdQueryDelegations("stake", cdc),
slashingcmd.GetCmdQuerySigningInfo("slashing", cdc),
)...) )...)
stakeCmd.AddCommand( stakeCmd.AddCommand(
client.PostCommands( client.PostCommands(
@ -93,6 +95,7 @@ func main() {
stakecmd.GetCmdEditValidator(cdc), stakecmd.GetCmdEditValidator(cdc),
stakecmd.GetCmdDelegate(cdc), stakecmd.GetCmdDelegate(cdc),
stakecmd.GetCmdUnbond(cdc), stakecmd.GetCmdUnbond(cdc),
slashingcmd.GetCmdUnrevoke(cdc),
)...) )...)
rootCmd.AddCommand( rootCmd.AddCommand(
stakeCmd, stakeCmd,

View File

@ -0,0 +1,6 @@
package cli
// nolint
const (
FlagAddressValidator = "address-validator"
)

View File

@ -0,0 +1,57 @@
package cli
import (
"fmt"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/tendermint/tmlibs/cli"
"github.com/cosmos/cosmos-sdk/client/context"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/wire" // XXX fix
"github.com/cosmos/cosmos-sdk/x/slashing"
)
// get the command to query signing info
func GetCmdQuerySigningInfo(storeName string, cdc *wire.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "signing_info [validator-pubkey]",
Short: "Query a validator's signing information",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
pk, err := sdk.GetValPubKeyBech32Cosmos(args[0])
if err != nil {
return err
}
key := slashing.GetValidatorSigningInfoKey(pk.Address())
ctx := context.NewCoreContextFromViper()
res, err := ctx.Query(key, storeName)
if err != nil {
return err
}
signingInfo := new(slashing.ValidatorSigningInfo)
cdc.MustUnmarshalBinary(res, signingInfo)
switch viper.Get(cli.OutputFlag) {
case "text":
human := signingInfo.HumanReadableString()
fmt.Println(human)
case "json":
// parse out the signing info
output, err := wire.MarshalJSONIndent(cdc, signingInfo)
if err != nil {
return err
}
fmt.Println(string(output))
}
return nil
},
}
return cmd
}

View File

@ -0,0 +1,42 @@
package cli
import (
"fmt"
"github.com/spf13/cobra"
"github.com/cosmos/cosmos-sdk/client/context"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/wire"
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
"github.com/cosmos/cosmos-sdk/x/slashing"
)
// create unrevoke command
func GetCmdUnrevoke(cdc *wire.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "unrevoke",
Args: cobra.ExactArgs(1),
Short: "unrevoke validator previously revoked for downtime",
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc))
validatorAddr, err := sdk.GetAccAddressBech32Cosmos(args[0])
if err != nil {
return err
}
msg := slashing.NewMsgUnrevoke(validatorAddr)
// build and sign the transaction, then broadcast to Tendermint
res, err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, msg, cdc)
if err != nil {
return err
}
fmt.Printf("Committed at block %d. Hash: %s\n", res.Height, res.Hash.String())
return nil
},
}
return cmd
}

View File

@ -2,14 +2,15 @@ package slashing
import ( import (
"encoding/binary" "encoding/binary"
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
) )
// Stored by *validator* address (not owner address) // Stored by *validator* address (not owner address)
func (k Keeper) getValidatorSigningInfo(ctx sdk.Context, address sdk.Address) (info validatorSigningInfo, found bool) { func (k Keeper) getValidatorSigningInfo(ctx sdk.Context, address sdk.Address) (info ValidatorSigningInfo, found bool) {
store := ctx.KVStore(k.storeKey) store := ctx.KVStore(k.storeKey)
bz := store.Get(validatorSigningInfoKey(address)) bz := store.Get(GetValidatorSigningInfoKey(address))
if bz == nil { if bz == nil {
found = false found = false
return return
@ -20,16 +21,16 @@ func (k Keeper) getValidatorSigningInfo(ctx sdk.Context, address sdk.Address) (i
} }
// Stored by *validator* address (not owner address) // Stored by *validator* address (not owner address)
func (k Keeper) setValidatorSigningInfo(ctx sdk.Context, address sdk.Address, info validatorSigningInfo) { func (k Keeper) setValidatorSigningInfo(ctx sdk.Context, address sdk.Address, info ValidatorSigningInfo) {
store := ctx.KVStore(k.storeKey) store := ctx.KVStore(k.storeKey)
bz := k.cdc.MustMarshalBinary(info) bz := k.cdc.MustMarshalBinary(info)
store.Set(validatorSigningInfoKey(address), bz) store.Set(GetValidatorSigningInfoKey(address), bz)
} }
// Stored by *validator* address (not owner address) // Stored by *validator* address (not owner address)
func (k Keeper) getValidatorSigningBitArray(ctx sdk.Context, address sdk.Address, index int64) (signed bool) { func (k Keeper) getValidatorSigningBitArray(ctx sdk.Context, address sdk.Address, index int64) (signed bool) {
store := ctx.KVStore(k.storeKey) store := ctx.KVStore(k.storeKey)
bz := store.Get(validatorSigningBitArrayKey(address, index)) bz := store.Get(GetValidatorSigningBitArrayKey(address, index))
if bz == nil { if bz == nil {
// lazy: treat empty key as unsigned // lazy: treat empty key as unsigned
signed = false signed = false
@ -43,23 +44,30 @@ func (k Keeper) getValidatorSigningBitArray(ctx sdk.Context, address sdk.Address
func (k Keeper) setValidatorSigningBitArray(ctx sdk.Context, address sdk.Address, index int64, signed bool) { func (k Keeper) setValidatorSigningBitArray(ctx sdk.Context, address sdk.Address, index int64, signed bool) {
store := ctx.KVStore(k.storeKey) store := ctx.KVStore(k.storeKey)
bz := k.cdc.MustMarshalBinary(signed) bz := k.cdc.MustMarshalBinary(signed)
store.Set(validatorSigningBitArrayKey(address, index), bz) store.Set(GetValidatorSigningBitArrayKey(address, index), bz)
} }
type validatorSigningInfo struct { // Signing info for a validator
type ValidatorSigningInfo struct {
StartHeight int64 `json:"start_height"` // height at which validator was first a candidate OR was unrevoked StartHeight int64 `json:"start_height"` // height at which validator was first a candidate OR was unrevoked
IndexOffset int64 `json:"index_offset"` // index offset into signed block bit array IndexOffset int64 `json:"index_offset"` // index offset into signed block bit array
JailedUntil int64 `json:"jailed_until"` // timestamp validator cannot be unrevoked until JailedUntil int64 `json:"jailed_until"` // timestamp validator cannot be unrevoked until
SignedBlocksCounter int64 `json:"signed_blocks_counter"` // signed blocks counter (to avoid scanning the array every time) SignedBlocksCounter int64 `json:"signed_blocks_counter"` // signed blocks counter (to avoid scanning the array every time)
} }
// Return human readable signing info
func (i ValidatorSigningInfo) HumanReadableString() string {
return fmt.Sprintf("Start height: %d, index offset: %d, jailed until: %d, signed blocks counter: %d",
i.StartHeight, i.IndexOffset, i.JailedUntil, i.SignedBlocksCounter)
}
// Stored by *validator* address (not owner address) // Stored by *validator* address (not owner address)
func validatorSigningInfoKey(v sdk.Address) []byte { func GetValidatorSigningInfoKey(v sdk.Address) []byte {
return append([]byte{0x01}, v.Bytes()...) return append([]byte{0x01}, v.Bytes()...)
} }
// Stored by *validator* address (not owner address) // Stored by *validator* address (not owner address)
func validatorSigningBitArrayKey(v sdk.Address, i int64) []byte { func GetValidatorSigningBitArrayKey(v sdk.Address, i int64) []byte {
b := make([]byte, 8) b := make([]byte, 8)
binary.LittleEndian.PutUint64(b, uint64(i)) binary.LittleEndian.PutUint64(b, uint64(i))
return append([]byte{0x02}, append(v.Bytes(), b...)...) return append([]byte{0x02}, append(v.Bytes(), b...)...)

View File

@ -10,7 +10,7 @@ func TestGetSetValidatorSigningInfo(t *testing.T) {
ctx, _, _, keeper := createTestInput(t) ctx, _, _, keeper := createTestInput(t)
info, found := keeper.getValidatorSigningInfo(ctx, addrs[0]) info, found := keeper.getValidatorSigningInfo(ctx, addrs[0])
require.False(t, found) require.False(t, found)
newInfo := validatorSigningInfo{ newInfo := ValidatorSigningInfo{
StartHeight: int64(4), StartHeight: int64(4),
IndexOffset: int64(3), IndexOffset: int64(3),
JailedUntil: int64(2), JailedUntil: int64(2),