Validator by pubkey, tests work-in-progress
This commit is contained in:
parent
adec1cd7a9
commit
b005f9f18d
|
@ -45,8 +45,9 @@ type ValidatorSet interface {
|
|||
IterateValidatorsBonded(Context,
|
||||
func(index int64, validator Validator) (stop bool))
|
||||
|
||||
Validator(Context, Address) Validator // get a particular validator by owner address
|
||||
TotalPower(Context) Rat // total power of the validator set
|
||||
Validator(Context, Address) Validator // get a particular validator by owner address
|
||||
ValidatorByPubKey(Context, crypto.PubKey) Validator // get a particular validator by public key
|
||||
TotalPower(Context) Rat // total power of the validator set
|
||||
}
|
||||
|
||||
//_______________________________________________________________________________
|
||||
|
|
|
@ -71,7 +71,10 @@ func (k Keeper) handleDoubleSign(ctx sdk.Context, height int64, timestamp int64,
|
|||
return
|
||||
}
|
||||
logger.Info(fmt.Sprintf("Confirmed double sign from %v at height %d, age of %d less than max age of %d", pubkey.Address(), height, age, MaxEvidenceAge))
|
||||
validator := k.stakeKeeper.Validator(ctx, pubkey.Address())
|
||||
validator := k.stakeKeeper.ValidatorByPubKey(ctx, pubkey)
|
||||
if validator == nil {
|
||||
panic(fmt.Errorf("Attempted to slash nonexistent validator with address %s", pubkey.Address()))
|
||||
}
|
||||
validator.Slash(ctx, height, SlashFractionDoubleSign)
|
||||
logger.Info(fmt.Sprintf("Slashed validator %s by fraction %v for double-sign at height %d", pubkey.Address(), SlashFractionDoubleSign, height))
|
||||
}
|
||||
|
@ -98,7 +101,10 @@ func (k Keeper) handleValidatorSignature(ctx sdk.Context, pubkey crypto.PubKey,
|
|||
}
|
||||
minHeight := signInfo.StartHeight + SignedBlocksWindow
|
||||
if height > minHeight && signInfo.SignedBlocksCounter < MinSignedPerWindow {
|
||||
validator := k.stakeKeeper.Validator(ctx, address)
|
||||
validator := k.stakeKeeper.ValidatorByPubKey(ctx, pubkey)
|
||||
if validator == nil {
|
||||
panic(fmt.Errorf("Attempted to slash nonexistent validator with address %s", pubkey.Address()))
|
||||
}
|
||||
validator.Slash(ctx, height, SlashFractionDowntime)
|
||||
validator.ForceUnbond(ctx, DowntimeUnbondDuration)
|
||||
logger.Info(fmt.Sprintf("Slashed validator %s by fraction %v and unbonded for downtime at height %d, cannot rebond for %ds",
|
||||
|
|
|
@ -1,17 +1,110 @@
|
|||
package slashing
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
// sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
||||
abci "github.com/tendermint/abci/types"
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
dbm "github.com/tendermint/tmlibs/db"
|
||||
"github.com/tendermint/tmlibs/log"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/store"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"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/stake"
|
||||
)
|
||||
|
||||
var (
|
||||
addrs = []sdk.Address{
|
||||
testAddr("A58856F0FD53BF058B4909A21AEC019107BA6160"),
|
||||
testAddr("A58856F0FD53BF058B4909A21AEC019107BA6161"),
|
||||
}
|
||||
pks = []crypto.PubKey{
|
||||
newPubKey("0B485CFC0EECC619440448436F8FC9DF40566F2369E72400281454CB552AFB50"),
|
||||
newPubKey("0B485CFC0EECC619440448436F8FC9DF40566F2369E72400281454CB552AFB51"),
|
||||
}
|
||||
initCoins int64 = 100
|
||||
)
|
||||
|
||||
func createTestCodec() *wire.Codec {
|
||||
cdc := wire.NewCodec()
|
||||
sdk.RegisterWire(cdc)
|
||||
auth.RegisterWire(cdc)
|
||||
bank.RegisterWire(cdc)
|
||||
stake.RegisterWire(cdc)
|
||||
wire.RegisterCrypto(cdc)
|
||||
return cdc
|
||||
}
|
||||
|
||||
func createTestInput(t *testing.T) (sdk.Context, bank.Keeper, stake.Keeper, Keeper) {
|
||||
keyAcc := sdk.NewKVStoreKey("acc")
|
||||
keyStake := sdk.NewKVStoreKey("stake")
|
||||
keySlashing := sdk.NewKVStoreKey("slashing")
|
||||
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)
|
||||
err := ms.LoadLatestVersion()
|
||||
require.Nil(t, err)
|
||||
ctx := sdk.NewContext(ms, abci.Header{}, false, nil, log.NewNopLogger(), nil)
|
||||
cdc := createTestCodec()
|
||||
accountMapper := auth.NewAccountMapper(cdc, keyAcc, &auth.BaseAccount{})
|
||||
ck := bank.NewKeeper(accountMapper)
|
||||
sk := stake.NewKeeper(cdc, keyStake, ck, stake.DefaultCodespace)
|
||||
stake.InitGenesis(ctx, sk, stake.DefaultGenesisState())
|
||||
for _, addr := range addrs {
|
||||
ck.AddCoins(ctx, addr, sdk.Coins{
|
||||
{sk.GetParams(ctx).BondDenom, initCoins},
|
||||
})
|
||||
}
|
||||
keeper := NewKeeper(cdc, keySlashing, sk, DefaultCodespace)
|
||||
return ctx, ck, sk, keeper
|
||||
}
|
||||
|
||||
func TestHandleDoubleSign(t *testing.T) {
|
||||
require.Equal(t, true, true)
|
||||
ctx, ck, sk, keeper := createTestInput(t)
|
||||
addr, val, amt := addrs[0], pks[0], int64(10)
|
||||
got := stake.NewHandler(sk)(ctx, newTestMsgDeclareCandidacy(addr, val, amt))
|
||||
require.True(t, got.IsOK())
|
||||
_ = sk.Tick(ctx)
|
||||
require.Equal(t, ck.GetCoins(ctx, addr), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins - amt}})
|
||||
keeper.handleDoubleSign(ctx, 0, 0, val)
|
||||
// TODO
|
||||
}
|
||||
|
||||
func TestHandleAbsentValidator(t *testing.T) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
func newPubKey(pk string) (res crypto.PubKey) {
|
||||
pkBytes, err := hex.DecodeString(pk)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
var pkEd crypto.PubKeyEd25519
|
||||
copy(pkEd[:], pkBytes[:])
|
||||
return pkEd
|
||||
}
|
||||
|
||||
func testAddr(addr string) sdk.Address {
|
||||
res, err := sdk.GetAddress(addr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func newTestMsgDeclareCandidacy(address sdk.Address, pubKey crypto.PubKey, amt int64) stake.MsgDeclareCandidacy {
|
||||
return stake.MsgDeclareCandidacy{
|
||||
Description: stake.Description{},
|
||||
ValidatorAddr: address,
|
||||
PubKey: pubKey,
|
||||
Bond: sdk.Coin{"steak", amt},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"github.com/cosmos/cosmos-sdk/wire"
|
||||
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||
abci "github.com/tendermint/abci/types"
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
)
|
||||
|
||||
// keeper of the staking store
|
||||
|
@ -38,6 +39,18 @@ func (k Keeper) GetValidator(ctx sdk.Context, addr sdk.Address) (validator Valid
|
|||
return k.getValidator(store, addr)
|
||||
}
|
||||
|
||||
// get a single validator by pubkey
|
||||
func (k Keeper) GetValidatorByPubKey(ctx sdk.Context, pubkey crypto.PubKey) (validator Validator, found bool) {
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
b := store.Get(GetValidatorByPubKeyKey(pubkey))
|
||||
if b == nil {
|
||||
return validator, false
|
||||
}
|
||||
var addr sdk.Address
|
||||
k.cdc.MustUnmarshalBinary(b, &addr)
|
||||
return k.getValidator(store, addr)
|
||||
}
|
||||
|
||||
// get a single validator (reuse store)
|
||||
func (k Keeper) getValidator(store sdk.KVStore, addr sdk.Address) (validator Validator, found bool) {
|
||||
b := store.Get(GetValidatorKey(addr))
|
||||
|
@ -710,6 +723,15 @@ func (k Keeper) Validator(ctx sdk.Context, addr sdk.Address) sdk.Validator {
|
|||
return val
|
||||
}
|
||||
|
||||
// get the sdk.validator for a particular pubkey
|
||||
func (k Keeper) ValidatorByPubKey(ctx sdk.Context, pubkey crypto.PubKey) sdk.Validator {
|
||||
val, found := k.GetValidatorByPubKey(ctx, pubkey)
|
||||
if !found {
|
||||
return nil
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
// total power from the bond
|
||||
func (k Keeper) TotalPower(ctx sdk.Context) sdk.Rat {
|
||||
pool := k.GetPool(ctx)
|
||||
|
|
|
@ -16,13 +16,14 @@ var (
|
|||
ParamKey = []byte{0x00} // key for parameters relating to staking
|
||||
PoolKey = []byte{0x01} // key for the staking pools
|
||||
ValidatorsKey = []byte{0x02} // prefix for each key to a validator
|
||||
ValidatorsBondedKey = []byte{0x03} // prefix for each key to bonded/actively validating validators
|
||||
ValidatorsByPowerKey = []byte{0x04} // prefix for each key to a validator sorted by power
|
||||
ValidatorCliffKey = []byte{0x05} // key for block-local tx index
|
||||
ValidatorPowerCliffKey = []byte{0x06} // key for block-local tx index
|
||||
TendermintUpdatesKey = []byte{0x07} // prefix for each key to a validator which is being updated
|
||||
DelegationKey = []byte{0x08} // prefix for each key to a delegator's bond
|
||||
IntraTxCounterKey = []byte{0x09} // key for block-local tx index
|
||||
ValidatorsByPubKeyKey = []byte{0x03} // prefix for each key to a validator by pubkey
|
||||
ValidatorsBondedKey = []byte{0x04} // prefix for each key to bonded/actively validating validators
|
||||
ValidatorsByPowerKey = []byte{0x05} // prefix for each key to a validator sorted by power
|
||||
ValidatorCliffKey = []byte{0x06} // key for block-local tx index
|
||||
ValidatorPowerCliffKey = []byte{0x07} // key for block-local tx index
|
||||
TendermintUpdatesKey = []byte{0x08} // prefix for each key to a validator which is being updated
|
||||
DelegationKey = []byte{0x09} // prefix for each key to a delegator's bond
|
||||
IntraTxCounterKey = []byte{0x10} // key for block-local tx index
|
||||
)
|
||||
|
||||
const maxDigitsForAccount = 12 // ~220,000,000 atoms created at launch
|
||||
|
@ -32,6 +33,11 @@ func GetValidatorKey(ownerAddr sdk.Address) []byte {
|
|||
return append(ValidatorsKey, ownerAddr.Bytes()...)
|
||||
}
|
||||
|
||||
// get the key for the validator with pubkey
|
||||
func GetValidatorByPubKeyKey(pubkey crypto.PubKey) []byte {
|
||||
return append(ValidatorsByPubKeyKey, pubkey.Bytes()...)
|
||||
}
|
||||
|
||||
// get the key for the current validator group, ordered like tendermint
|
||||
func GetValidatorsBondedKey(pk crypto.PubKey) []byte {
|
||||
addr := pk.Address()
|
||||
|
|
Loading…
Reference in New Issue