pulling in stuff from fee-distr PR

This commit is contained in:
rigelrozanski 2018-09-20 20:30:18 -04:00
parent 8721dd6ff8
commit 4e4749da9d
23 changed files with 341 additions and 185 deletions

View File

@ -34,9 +34,9 @@ func handleMsgUnjail(ctx sdk.Context, msg MsgUnjail, k Keeper) sdk.Result {
return ErrValidatorNotJailed(k.codespace).Result() return ErrValidatorNotJailed(k.codespace).Result()
} }
addr := sdk.ConsAddress(validator.GetPubKey().Address()) consAddr := sdk.ConsAddress(validator.GetPubKey().Address())
info, found := k.getValidatorSigningInfo(ctx, addr) info, found := k.getValidatorSigningInfo(ctx, consAddr)
if !found { if !found {
return ErrNoValidatorForAddress(k.codespace).Result() return ErrNoValidatorForAddress(k.codespace).Result()
} }
@ -49,9 +49,9 @@ func handleMsgUnjail(ctx sdk.Context, msg MsgUnjail, k Keeper) sdk.Result {
// update the starting height so the validator can't be immediately jailed // update the starting height so the validator can't be immediately jailed
// again // again
info.StartHeight = ctx.BlockHeight() info.StartHeight = ctx.BlockHeight()
k.setValidatorSigningInfo(ctx, addr, info) k.setValidatorSigningInfo(ctx, consAddr, info)
k.validatorSet.Unjail(ctx, validator.GetPubKey()) k.validatorSet.Unjail(ctx, consAddr)
tags := sdk.NewTags("action", []byte("unjail"), "validator", []byte(msg.ValidatorAddr.String())) tags := sdk.NewTags("action", []byte("unjail"), "validator", []byte(msg.ValidatorAddr.String()))

View File

@ -22,25 +22,34 @@ func (k Keeper) onValidatorBeginUnbonding(ctx sdk.Context, address sdk.ConsAddre
k.addOrUpdateValidatorSlashingPeriod(ctx, slashingPeriod) k.addOrUpdateValidatorSlashingPeriod(ctx, slashingPeriod)
} }
// Wrapper struct for sdk.ValidatorHooks //_________________________________________________________________________________________
type ValidatorHooks struct {
// Wrapper struct
type Hooks struct {
k Keeper k Keeper
} }
// Assert implementation var _ sdk.StakingHooks = Hooks{}
var _ sdk.ValidatorHooks = ValidatorHooks{}
// Return a sdk.ValidatorHooks interface over the wrapper struct // Return the wrapper struct
func (k Keeper) ValidatorHooks() sdk.ValidatorHooks { func (k Keeper) Hooks() Hooks {
return ValidatorHooks{k} return Hooks{k}
} }
// Implements sdk.ValidatorHooks // Implements sdk.ValidatorHooks
func (v ValidatorHooks) OnValidatorBonded(ctx sdk.Context, address sdk.ConsAddress) { func (h Hooks) OnValidatorBonded(ctx sdk.Context, address sdk.ConsAddress) {
v.k.onValidatorBonded(ctx, address) h.k.onValidatorBonded(ctx, address)
} }
// Implements sdk.ValidatorHooks // Implements sdk.ValidatorHooks
func (v ValidatorHooks) OnValidatorBeginUnbonding(ctx sdk.Context, address sdk.ConsAddress) { func (h Hooks) OnValidatorBeginUnbonding(ctx sdk.Context, address sdk.ConsAddress) {
v.k.onValidatorBeginUnbonding(ctx, address) h.k.onValidatorBeginUnbonding(ctx, address)
} }
// nolint - unused hooks
func (h Hooks) OnValidatorCreated(_ sdk.Context, _ sdk.ValAddress) {}
func (h Hooks) OnValidatorCommissionChange(_ sdk.Context, _ sdk.ValAddress) {}
func (h Hooks) OnValidatorRemoved(_ sdk.Context, _ sdk.ValAddress) {}
func (h Hooks) OnDelegationCreated(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) {}
func (h Hooks) OnDelegationSharesModified(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) {}
func (h Hooks) OnDelegationRemoved(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) {}

View File

@ -40,10 +40,10 @@ func (k Keeper) handleDoubleSign(ctx sdk.Context, addr crypto.Address, infractio
logger := ctx.Logger().With("module", "x/slashing") logger := ctx.Logger().With("module", "x/slashing")
time := ctx.BlockHeader().Time time := ctx.BlockHeader().Time
age := time.Sub(timestamp) age := time.Sub(timestamp)
address := sdk.ConsAddress(addr) consAddr := sdk.ConsAddress(addr)
pubkey, err := k.getPubkey(ctx, addr) pubkey, err := k.getPubkey(ctx, addr)
if err != nil { if err != nil {
panic(fmt.Sprintf("Validator address %v not found", addr)) panic(fmt.Sprintf("Validator consensus-address %v not found", consAddr))
} }
// Double sign too old // Double sign too old
@ -59,37 +59,38 @@ func (k Keeper) handleDoubleSign(ctx sdk.Context, addr crypto.Address, infractio
// Cap the amount slashed to the penalty for the worst infraction // Cap the amount slashed to the penalty for the worst infraction
// within the slashing period when this infraction was committed // within the slashing period when this infraction was committed
fraction := k.SlashFractionDoubleSign(ctx) fraction := k.SlashFractionDoubleSign(ctx)
revisedFraction := k.capBySlashingPeriod(ctx, address, fraction, infractionHeight) revisedFraction := k.capBySlashingPeriod(ctx, consAddr, fraction, infractionHeight)
logger.Info(fmt.Sprintf("Fraction slashed capped by slashing period from %v to %v", fraction, revisedFraction)) logger.Info(fmt.Sprintf("Fraction slashed capped by slashing period from %v to %v", fraction, revisedFraction))
// Slash validator // Slash validator
k.validatorSet.Slash(ctx, pubkey, infractionHeight, power, revisedFraction) k.validatorSet.Slash(ctx, consAddr, infractionHeight, power, revisedFraction)
// Jail validator // Jail validator
k.validatorSet.Jail(ctx, pubkey) k.validatorSet.Jail(ctx, consAddr)
// Set validator jail duration // Set validator jail duration
signInfo, found := k.getValidatorSigningInfo(ctx, address) signInfo, found := k.getValidatorSigningInfo(ctx, consAddr)
if !found { if !found {
panic(fmt.Sprintf("Expected signing info for validator %s but not found", address)) panic(fmt.Sprintf("Expected signing info for validator %s but not found", consAddr))
} }
signInfo.JailedUntil = time.Add(k.DoubleSignUnbondDuration(ctx)) signInfo.JailedUntil = time.Add(k.DoubleSignUnbondDuration(ctx))
k.setValidatorSigningInfo(ctx, address, signInfo) k.setValidatorSigningInfo(ctx, consAddr, signInfo)
} }
// handle a validator signature, must be called once per validator per block // handle a validator signature, must be called once per validator per block
// TODO refactor to take in a consensus address, additionally should maybe just take in the pubkey too
// nolint gocyclo // nolint gocyclo
func (k Keeper) handleValidatorSignature(ctx sdk.Context, addr crypto.Address, power int64, signed bool) { func (k Keeper) handleValidatorSignature(ctx sdk.Context, addr crypto.Address, power int64, signed bool) {
logger := ctx.Logger().With("module", "x/slashing") logger := ctx.Logger().With("module", "x/slashing")
height := ctx.BlockHeight() height := ctx.BlockHeight()
address := sdk.ConsAddress(addr) consAddr := sdk.ConsAddress(addr)
pubkey, err := k.getPubkey(ctx, addr) pubkey, err := k.getPubkey(ctx, addr)
if err != nil { if err != nil {
panic(fmt.Sprintf("Validator address %v not found", addr)) panic(fmt.Sprintf("Validator consensus-address %v not found", consAddr))
} }
// Local index, so counts blocks validator *should* have signed // Local index, so counts blocks validator *should* have signed
// Will use the 0-value default signing info if not present, except for start height // Will use the 0-value default signing info if not present, except for start height
signInfo, found := k.getValidatorSigningInfo(ctx, address) signInfo, found := k.getValidatorSigningInfo(ctx, consAddr)
if !found { if !found {
// If this validator has never been seen before, construct a new SigningInfo with the correct start height // If this validator has never been seen before, construct a new SigningInfo with the correct start height
signInfo = NewValidatorSigningInfo(height, 0, time.Unix(0, 0), 0) signInfo = NewValidatorSigningInfo(height, 0, time.Unix(0, 0), 0)
@ -100,16 +101,16 @@ func (k Keeper) handleValidatorSignature(ctx sdk.Context, addr crypto.Address, p
// Update signed block bit array & counter // Update signed block bit array & counter
// This counter just tracks the sum of the bit array // This counter just tracks the sum of the bit array
// That way we avoid needing to read/write the whole array each time // That way we avoid needing to read/write the whole array each time
previous := k.getValidatorSigningBitArray(ctx, address, index) previous := k.getValidatorSigningBitArray(ctx, consAddr, index)
if previous == signed { if previous == signed {
// Array value at this index has not changed, no need to update counter // Array value at this index has not changed, no need to update counter
} else if previous && !signed { } else if previous && !signed {
// Array value has changed from signed to unsigned, decrement counter // Array value has changed from signed to unsigned, decrement counter
k.setValidatorSigningBitArray(ctx, address, index, false) k.setValidatorSigningBitArray(ctx, consAddr, index, false)
signInfo.SignedBlocksCounter-- signInfo.SignedBlocksCounter--
} else if !previous && signed { } else if !previous && signed {
// Array value has changed from unsigned to signed, increment counter // Array value has changed from unsigned to signed, increment counter
k.setValidatorSigningBitArray(ctx, address, index, true) k.setValidatorSigningBitArray(ctx, consAddr, index, true)
signInfo.SignedBlocksCounter++ signInfo.SignedBlocksCounter++
} }
@ -118,13 +119,13 @@ func (k Keeper) handleValidatorSignature(ctx sdk.Context, addr crypto.Address, p
} }
minHeight := signInfo.StartHeight + k.SignedBlocksWindow(ctx) minHeight := signInfo.StartHeight + k.SignedBlocksWindow(ctx)
if height > minHeight && signInfo.SignedBlocksCounter < k.MinSignedPerWindow(ctx) { if height > minHeight && signInfo.SignedBlocksCounter < k.MinSignedPerWindow(ctx) {
validator := k.validatorSet.ValidatorByPubKey(ctx, pubkey) validator := k.validatorSet.ValidatorByConsAddr(ctx, consAddr)
if validator != nil && !validator.GetJailed() { if validator != nil && !validator.GetJailed() {
// Downtime confirmed: slash and jail the validator // Downtime confirmed: slash and jail the validator
logger.Info(fmt.Sprintf("Validator %s past min height of %d and below signed blocks threshold of %d", logger.Info(fmt.Sprintf("Validator %s past min height of %d and below signed blocks threshold of %d",
pubkey.Address(), minHeight, k.MinSignedPerWindow(ctx))) pubkey.Address(), minHeight, k.MinSignedPerWindow(ctx)))
k.validatorSet.Slash(ctx, pubkey, height, power, k.SlashFractionDowntime(ctx)) k.validatorSet.Slash(ctx, consAddr, height, power, k.SlashFractionDowntime(ctx))
k.validatorSet.Jail(ctx, pubkey) k.validatorSet.Jail(ctx, consAddr)
signInfo.JailedUntil = ctx.BlockHeader().Time.Add(k.DowntimeUnbondDuration(ctx)) signInfo.JailedUntil = ctx.BlockHeader().Time.Add(k.DowntimeUnbondDuration(ctx))
} else { } else {
// Validator was (a) not found or (b) already jailed, don't slash // Validator was (a) not found or (b) already jailed, don't slash
@ -134,7 +135,7 @@ func (k Keeper) handleValidatorSignature(ctx sdk.Context, addr crypto.Address, p
} }
// Set the updated signing info // Set the updated signing info
k.setValidatorSigningInfo(ctx, address, signInfo) k.setValidatorSigningInfo(ctx, consAddr, signInfo)
} }
// AddValidators adds the validators to the keepers validator addr to pubkey mapping. // AddValidators adds the validators to the keepers validator addr to pubkey mapping.

View File

@ -18,13 +18,16 @@ func init() {
defaultDoubleSignUnbondDuration = 60 * 60 defaultDoubleSignUnbondDuration = 60 * 60
} }
// ______________________________________________________________
// Test that a validator is slashed correctly // Test that a validator is slashed correctly
// when we discover evidence of infraction // when we discover evidence of infraction
// TODO fix this test to not be using the same pubkey/address for signing and operating, it's confusing
func TestHandleDoubleSign(t *testing.T) { func TestHandleDoubleSign(t *testing.T) {
// initial setup // initial setup
ctx, ck, sk, _, keeper := createTestInput(t) ctx, ck, sk, _, keeper := createTestInput(t)
sk = sk.WithValidatorHooks(keeper.ValidatorHooks()) sk = sk.WithHooks(keeper.Hooks())
amtInt := int64(100) amtInt := int64(100)
addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt) addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt)
got := stake.NewHandler(sk)(ctx, newTestMsgCreateValidator(addr, val, amt)) got := stake.NewHandler(sk)(ctx, newTestMsgCreateValidator(addr, val, amt))
@ -43,7 +46,7 @@ func TestHandleDoubleSign(t *testing.T) {
// should be jailed // should be jailed
require.True(t, sk.Validator(ctx, addr).GetJailed()) require.True(t, sk.Validator(ctx, addr).GetJailed())
// unjail to measure power // unjail to measure power
sk.Unjail(ctx, val) sk.Unjail(ctx, sdk.ConsAddress(addr)) // TODO distinguish cons address
// power should be reduced // power should be reduced
require.Equal( require.Equal(
t, sdk.NewDecFromInt(amt).Mul(sdk.NewDec(19).Quo(sdk.NewDec(20))), t, sdk.NewDecFromInt(amt).Mul(sdk.NewDec(19).Quo(sdk.NewDec(20))),
@ -61,14 +64,16 @@ func TestHandleDoubleSign(t *testing.T) {
// Test that the amount a validator is slashed for multiple double signs // Test that the amount a validator is slashed for multiple double signs
// is correctly capped by the slashing period in which they were committed // is correctly capped by the slashing period in which they were committed
// TODO properly distinguish between consensus and operator address is variable names
func TestSlashingPeriodCap(t *testing.T) { func TestSlashingPeriodCap(t *testing.T) {
// initial setup // initial setup
ctx, ck, sk, _, keeper := createTestInput(t) ctx, ck, sk, _, keeper := createTestInput(t)
sk = sk.WithValidatorHooks(keeper.ValidatorHooks()) sk = sk.WithHooks(keeper.Hooks())
amtInt := int64(100) amtInt := int64(100)
addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt) addr, amt := addrs[0], sdk.NewInt(amtInt)
got := stake.NewHandler(sk)(ctx, newTestMsgCreateValidator(addr, val, amt)) valConsPubKey, valConsAddr := pks[0], sdk.ConsAddress(pks[0].Address())
got := stake.NewHandler(sk)(ctx, newTestMsgCreateValidator(addr, valConsPubKey, amt))
require.True(t, got.IsOK()) require.True(t, got.IsOK())
validatorUpdates := stake.EndBlocker(ctx, sk) validatorUpdates := stake.EndBlocker(ctx, sk)
keeper.AddValidators(ctx, validatorUpdates) keeper.AddValidators(ctx, validatorUpdates)
@ -76,39 +81,39 @@ func TestSlashingPeriodCap(t *testing.T) {
require.True(t, sdk.NewDecFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower())) require.True(t, sdk.NewDecFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower()))
// handle a signature to set signing info // handle a signature to set signing info
keeper.handleValidatorSignature(ctx, val.Address(), amtInt, true) keeper.handleValidatorSignature(ctx, valConsPubKey.Address(), amtInt, true)
// double sign less than max age // double sign less than max age
keeper.handleDoubleSign(ctx, val.Address(), 0, time.Unix(0, 0), amtInt) keeper.handleDoubleSign(ctx, valConsPubKey.Address(), 0, time.Unix(0, 0), amtInt)
// should be jailed // should be jailed
require.True(t, sk.Validator(ctx, addr).GetJailed()) require.True(t, sk.Validator(ctx, addr).GetJailed())
// update block height // update block height
ctx = ctx.WithBlockHeight(int64(1)) ctx = ctx.WithBlockHeight(int64(1))
// unjail to measure power // unjail to measure power
sk.Unjail(ctx, val) sk.Unjail(ctx, valConsAddr)
// power should be reduced // power should be reduced
expectedPower := sdk.NewDecFromInt(amt).Mul(sdk.NewDec(19).Quo(sdk.NewDec(20))) expectedPower := sdk.NewDecFromInt(amt).Mul(sdk.NewDec(19).Quo(sdk.NewDec(20)))
require.Equal(t, expectedPower, sk.Validator(ctx, addr).GetPower()) require.Equal(t, expectedPower, sk.Validator(ctx, addr).GetPower())
// double sign again, same slashing period // double sign again, same slashing period
keeper.handleDoubleSign(ctx, val.Address(), 0, time.Unix(0, 0), amtInt) keeper.handleDoubleSign(ctx, valConsPubKey.Address(), 0, time.Unix(0, 0), amtInt)
// should be jailed // should be jailed
require.True(t, sk.Validator(ctx, addr).GetJailed()) require.True(t, sk.Validator(ctx, addr).GetJailed())
// update block height // update block height
ctx = ctx.WithBlockHeight(int64(2)) ctx = ctx.WithBlockHeight(int64(2))
// unjail to measure power // unjail to measure power
sk.Unjail(ctx, val) sk.Unjail(ctx, valConsAddr)
// power should be equal, no more should have been slashed // power should be equal, no more should have been slashed
expectedPower = sdk.NewDecFromInt(amt).Mul(sdk.NewDec(19).Quo(sdk.NewDec(20))) expectedPower = sdk.NewDecFromInt(amt).Mul(sdk.NewDec(19).Quo(sdk.NewDec(20)))
require.Equal(t, expectedPower, sk.Validator(ctx, addr).GetPower()) require.Equal(t, expectedPower, sk.Validator(ctx, addr).GetPower())
// double sign again, new slashing period // double sign again, new slashing period
keeper.handleDoubleSign(ctx, val.Address(), 2, time.Unix(0, 0), amtInt) keeper.handleDoubleSign(ctx, valConsPubKey.Address(), 2, time.Unix(0, 0), amtInt)
// should be jailed // should be jailed
require.True(t, sk.Validator(ctx, addr).GetJailed()) require.True(t, sk.Validator(ctx, addr).GetJailed())
// unjail to measure power // unjail to measure power
sk.Unjail(ctx, val) sk.Unjail(ctx, valConsAddr)
// power should be reduced // power should be reduced
expectedPower = sdk.NewDecFromInt(amt).Mul(sdk.NewDec(18).Quo(sdk.NewDec(20))) expectedPower = sdk.NewDecFromInt(amt).Mul(sdk.NewDec(18).Quo(sdk.NewDec(20)))
require.Equal(t, expectedPower, sk.Validator(ctx, addr).GetPower()) require.Equal(t, expectedPower, sk.Validator(ctx, addr).GetPower())
@ -120,7 +125,7 @@ func TestHandleAbsentValidator(t *testing.T) {
// initial setup // initial setup
ctx, ck, sk, _, keeper := createTestInput(t) ctx, ck, sk, _, keeper := createTestInput(t)
sk = sk.WithValidatorHooks(keeper.ValidatorHooks()) sk = sk.WithHooks(keeper.Hooks())
amtInt := int64(100) amtInt := int64(100)
addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt) addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt)
sh := stake.NewHandler(sk) sh := stake.NewHandler(sk)
@ -162,7 +167,7 @@ func TestHandleAbsentValidator(t *testing.T) {
require.Equal(t, keeper.SignedBlocksWindow(ctx)-keeper.MinSignedPerWindow(ctx), info.SignedBlocksCounter) require.Equal(t, keeper.SignedBlocksWindow(ctx)-keeper.MinSignedPerWindow(ctx), info.SignedBlocksCounter)
// validator should be bonded still // validator should be bonded still
validator, _ := sk.GetValidatorByPubKey(ctx, val) validator, _ := sk.GetValidatorByConsPubKey(ctx, val)
require.Equal(t, sdk.Bonded, validator.GetStatus()) require.Equal(t, sdk.Bonded, validator.GetStatus())
pool := sk.GetPool(ctx) pool := sk.GetPool(ctx)
require.Equal(t, amtInt, pool.BondedTokens.RoundInt64()) require.Equal(t, amtInt, pool.BondedTokens.RoundInt64())
@ -176,7 +181,7 @@ func TestHandleAbsentValidator(t *testing.T) {
require.Equal(t, keeper.SignedBlocksWindow(ctx)-keeper.MinSignedPerWindow(ctx)-1, info.SignedBlocksCounter) require.Equal(t, keeper.SignedBlocksWindow(ctx)-keeper.MinSignedPerWindow(ctx)-1, info.SignedBlocksCounter)
// validator should have been jailed // validator should have been jailed
validator, _ = sk.GetValidatorByPubKey(ctx, val) validator, _ = sk.GetValidatorByConsPubKey(ctx, val)
require.Equal(t, sdk.Unbonding, validator.GetStatus()) require.Equal(t, sdk.Unbonding, validator.GetStatus())
// unrevocation should fail prior to jail expiration // unrevocation should fail prior to jail expiration
@ -189,7 +194,7 @@ func TestHandleAbsentValidator(t *testing.T) {
require.True(t, got.IsOK()) require.True(t, got.IsOK())
// validator should be rebonded now // validator should be rebonded now
validator, _ = sk.GetValidatorByPubKey(ctx, val) validator, _ = sk.GetValidatorByConsPubKey(ctx, val)
require.Equal(t, sdk.Bonded, validator.GetStatus()) require.Equal(t, sdk.Bonded, validator.GetStatus())
// validator should have been slashed // validator should have been slashed
@ -207,7 +212,7 @@ func TestHandleAbsentValidator(t *testing.T) {
height++ height++
ctx = ctx.WithBlockHeight(height) ctx = ctx.WithBlockHeight(height)
keeper.handleValidatorSignature(ctx, val.Address(), amtInt, false) keeper.handleValidatorSignature(ctx, val.Address(), amtInt, false)
validator, _ = sk.GetValidatorByPubKey(ctx, val) validator, _ = sk.GetValidatorByConsPubKey(ctx, val)
require.Equal(t, sdk.Bonded, validator.GetStatus()) require.Equal(t, sdk.Bonded, validator.GetStatus())
// 500 signed blocks // 500 signed blocks
@ -223,7 +228,7 @@ func TestHandleAbsentValidator(t *testing.T) {
ctx = ctx.WithBlockHeight(height) ctx = ctx.WithBlockHeight(height)
keeper.handleValidatorSignature(ctx, val.Address(), amtInt, false) keeper.handleValidatorSignature(ctx, val.Address(), amtInt, false)
} }
validator, _ = sk.GetValidatorByPubKey(ctx, val) validator, _ = sk.GetValidatorByConsPubKey(ctx, val)
require.Equal(t, sdk.Unbonding, validator.GetStatus()) require.Equal(t, sdk.Unbonding, validator.GetStatus())
} }
@ -258,7 +263,7 @@ func TestHandleNewValidator(t *testing.T) {
require.Equal(t, time.Unix(0, 0).UTC(), info.JailedUntil) require.Equal(t, time.Unix(0, 0).UTC(), info.JailedUntil)
// validator should be bonded still, should not have been jailed or slashed // validator should be bonded still, should not have been jailed or slashed
validator, _ := sk.GetValidatorByPubKey(ctx, val) validator, _ := sk.GetValidatorByConsPubKey(ctx, val)
require.Equal(t, sdk.Bonded, validator.GetStatus()) require.Equal(t, sdk.Bonded, validator.GetStatus())
pool := sk.GetPool(ctx) pool := sk.GetPool(ctx)
require.Equal(t, int64(100), pool.BondedTokens.RoundInt64()) require.Equal(t, int64(100), pool.BondedTokens.RoundInt64())
@ -292,7 +297,7 @@ func TestHandleAlreadyJailed(t *testing.T) {
} }
// validator should have been jailed and slashed // validator should have been jailed and slashed
validator, _ := sk.GetValidatorByPubKey(ctx, val) validator, _ := sk.GetValidatorByConsPubKey(ctx, val)
require.Equal(t, sdk.Unbonding, validator.GetStatus()) require.Equal(t, sdk.Unbonding, validator.GetStatus())
// validator should have been slashed // validator should have been slashed
@ -303,7 +308,7 @@ func TestHandleAlreadyJailed(t *testing.T) {
keeper.handleValidatorSignature(ctx, val.Address(), amtInt, false) keeper.handleValidatorSignature(ctx, val.Address(), amtInt, false)
// validator should not have been slashed twice // validator should not have been slashed twice
validator, _ = sk.GetValidatorByPubKey(ctx, val) validator, _ = sk.GetValidatorByConsPubKey(ctx, val)
require.Equal(t, amtInt-1, validator.GetTokens().RoundInt64()) require.Equal(t, amtInt-1, validator.GetTokens().RoundInt64())
} }

View File

@ -78,7 +78,7 @@ func TestBeginBlocker(t *testing.T) {
} }
// validator should be jailed // validator should be jailed
validator, found := sk.GetValidatorByPubKey(ctx, pk) validator, found := sk.GetValidatorByConsPubKey(ctx, pk)
require.True(t, found) require.True(t, found)
require.Equal(t, sdk.Unbonding, validator.GetStatus()) require.Equal(t, sdk.Unbonding, validator.GetStatus())
} }

View File

@ -48,8 +48,8 @@ func init() {
fsDescriptionEdit.String(FlagIdentity, types.DoNotModifyDesc, "optional identity signature (ex. UPort or Keybase)") fsDescriptionEdit.String(FlagIdentity, types.DoNotModifyDesc, "optional identity signature (ex. UPort or Keybase)")
fsDescriptionEdit.String(FlagWebsite, types.DoNotModifyDesc, "optional website") fsDescriptionEdit.String(FlagWebsite, types.DoNotModifyDesc, "optional website")
fsDescriptionEdit.String(FlagDetails, types.DoNotModifyDesc, "optional details") fsDescriptionEdit.String(FlagDetails, types.DoNotModifyDesc, "optional details")
fsValidator.String(FlagAddressValidator, "", "hex address of the validator") fsValidator.String(FlagAddressValidator, "", "bech address of the validator")
fsDelegator.String(FlagAddressDelegator, "", "hex address of the delegator") fsDelegator.String(FlagAddressDelegator, "", "bech address of the delegator")
fsRedelegation.String(FlagAddressValidatorSrc, "", "hex address of the source validator") fsRedelegation.String(FlagAddressValidatorSrc, "", "bech address of the source validator")
fsRedelegation.String(FlagAddressValidatorDst, "", "hex address of the destination validator") fsRedelegation.String(FlagAddressValidatorDst, "", "bech address of the destination validator")
} }

View File

@ -32,7 +32,7 @@ func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) (res [
} }
// Manually set indexes for the first time // Manually set indexes for the first time
keeper.SetValidatorByPubKeyIndex(ctx, validator) keeper.SetValidatorByConsAddr(ctx, validator)
keeper.SetValidatorByPowerIndex(ctx, validator, data.Pool) keeper.SetValidatorByPowerIndex(ctx, validator, data.Pool)
if validator.Status == sdk.Bonded { if validator.Status == sdk.Bonded {

View File

@ -68,7 +68,7 @@ func handleMsgCreateValidator(ctx sdk.Context, msg types.MsgCreateValidator, k k
if found { if found {
return ErrValidatorOwnerExists(k.Codespace()).Result() return ErrValidatorOwnerExists(k.Codespace()).Result()
} }
_, found = k.GetValidatorByPubKey(ctx, msg.PubKey) _, found = k.GetValidatorByConsPubKey(ctx, msg.PubKey)
if found { if found {
return ErrValidatorPubKeyExists(k.Codespace()).Result() return ErrValidatorPubKeyExists(k.Codespace()).Result()
} }
@ -78,7 +78,7 @@ func handleMsgCreateValidator(ctx sdk.Context, msg types.MsgCreateValidator, k k
validator := NewValidator(msg.ValidatorAddr, msg.PubKey, msg.Description) validator := NewValidator(msg.ValidatorAddr, msg.PubKey, msg.Description)
k.SetValidator(ctx, validator) k.SetValidator(ctx, validator)
k.SetValidatorByPubKeyIndex(ctx, validator) k.SetValidatorByConsAddr(ctx, validator)
// move coins from the msg.Address account to a (self-delegation) delegator account // move coins from the msg.Address account to a (self-delegation) delegator account
// the validator account and global shares are updated within here // the validator account and global shares are updated within here
@ -87,6 +87,11 @@ func handleMsgCreateValidator(ctx sdk.Context, msg types.MsgCreateValidator, k k
return err.Result() return err.Result()
} }
// call the hook if present
k.OnValidatorCreated(ctx, validator.OperatorAddr)
accAddr := sdk.AccAddress(validator.OperatorAddr)
k.OnDelegationCreated(ctx, accAddr, validator.OperatorAddr)
tags := sdk.NewTags( tags := sdk.NewTags(
tags.Action, tags.ActionCreateValidator, tags.Action, tags.ActionCreateValidator,
tags.DstValidator, []byte(msg.ValidatorAddr.String()), tags.DstValidator, []byte(msg.ValidatorAddr.String()),
@ -146,6 +151,9 @@ func handleMsgDelegate(ctx sdk.Context, msg types.MsgDelegate, k keeper.Keeper)
return err.Result() return err.Result()
} }
// call the hook if present
k.OnDelegationCreated(ctx, msg.DelegatorAddr, validator.OperatorAddr)
tags := sdk.NewTags( tags := sdk.NewTags(
tags.Action, tags.ActionDelegate, tags.Action, tags.ActionDelegate,
tags.Delegator, []byte(msg.DelegatorAddr.String()), tags.Delegator, []byte(msg.DelegatorAddr.String()),

View File

@ -81,8 +81,9 @@ func TestValidatorByPowerIndex(t *testing.T) {
require.True(t, got.IsOK(), "expected create-validator to be ok, got %v", got) require.True(t, got.IsOK(), "expected create-validator to be ok, got %v", got)
// slash and jail the first validator // slash and jail the first validator
keeper.Slash(ctx, keep.PKs[0], 0, initBond, sdk.NewDecWithPrec(5, 1)) consAddr0 := sdk.ConsAddress(keep.PKs[0].Address())
keeper.Jail(ctx, keep.PKs[0]) keeper.Slash(ctx, consAddr0, 0, initBond, sdk.NewDecWithPrec(5, 1))
keeper.Jail(ctx, consAddr0)
validator, found = keeper.GetValidator(ctx, validatorAddr) validator, found = keeper.GetValidator(ctx, validatorAddr)
require.True(t, found) require.True(t, found)
require.Equal(t, sdk.Unbonding, validator.Status) // ensure is unbonding require.Equal(t, sdk.Unbonding, validator.Status) // ensure is unbonding
@ -198,11 +199,12 @@ func TestLegacyValidatorDelegations(t *testing.T) {
setInstantUnbondPeriod(keeper, ctx) setInstantUnbondPeriod(keeper, ctx)
bondAmount := int64(10) bondAmount := int64(10)
valAddr, valPubKey := sdk.ValAddress(keep.Addrs[0]), keep.PKs[0] valAddr := sdk.ValAddress(keep.Addrs[0])
valConsPubKey, valConsAddr := keep.PKs[0], sdk.ConsAddress(keep.PKs[0].Address())
delAddr := keep.Addrs[1] delAddr := keep.Addrs[1]
// create validator // create validator
msgCreateVal := newTestMsgCreateValidator(valAddr, valPubKey, bondAmount) msgCreateVal := newTestMsgCreateValidator(valAddr, valConsPubKey, bondAmount)
got := handleMsgCreateValidator(ctx, msgCreateVal, keeper) got := handleMsgCreateValidator(ctx, msgCreateVal, keeper)
require.True(t, got.IsOK(), "expected create validator msg to be ok, got %v", got) require.True(t, got.IsOK(), "expected create validator msg to be ok, got %v", got)
@ -264,7 +266,7 @@ func TestLegacyValidatorDelegations(t *testing.T) {
require.Equal(t, bondAmount*2, validator.Tokens.RoundInt64()) require.Equal(t, bondAmount*2, validator.Tokens.RoundInt64())
// unjail the validator now that is has non-zero self-delegated shares // unjail the validator now that is has non-zero self-delegated shares
keeper.Unjail(ctx, valPubKey) keeper.Unjail(ctx, valConsAddr)
// verify the validator can now accept delegations // verify the validator can now accept delegations
msgDelegate = newTestMsgDelegate(delAddr, valAddr, bondAmount) msgDelegate = newTestMsgDelegate(delAddr, valAddr, bondAmount)
@ -911,6 +913,7 @@ func TestCliffValidator(t *testing.T) {
func TestBondUnbondRedelegateSlashTwice(t *testing.T) { func TestBondUnbondRedelegateSlashTwice(t *testing.T) {
ctx, _, keeper := keep.CreateTestInput(t, false, 1000) ctx, _, keeper := keep.CreateTestInput(t, false, 1000)
valA, valB, del := sdk.ValAddress(keep.Addrs[0]), sdk.ValAddress(keep.Addrs[1]), keep.Addrs[2] valA, valB, del := sdk.ValAddress(keep.Addrs[0]), sdk.ValAddress(keep.Addrs[1]), keep.Addrs[2]
consAddr0 := sdk.ConsAddress(keep.PKs[0].Address())
msgCreateValidator := newTestMsgCreateValidator(valA, keep.PKs[0], 10) msgCreateValidator := newTestMsgCreateValidator(valA, keep.PKs[0], 10)
got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper) got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
@ -944,7 +947,7 @@ func TestBondUnbondRedelegateSlashTwice(t *testing.T) {
require.Equal(t, sdk.NewDec(6), delegation.Shares) require.Equal(t, sdk.NewDec(6), delegation.Shares)
// slash the validator by half // slash the validator by half
keeper.Slash(ctx, keep.PKs[0], 0, 20, sdk.NewDecWithPrec(5, 1)) keeper.Slash(ctx, consAddr0, 0, 20, sdk.NewDecWithPrec(5, 1))
// unbonding delegation should have been slashed by half // unbonding delegation should have been slashed by half
unbonding, found := keeper.GetUnbondingDelegation(ctx, del, valA) unbonding, found := keeper.GetUnbondingDelegation(ctx, del, valA)
@ -968,7 +971,7 @@ func TestBondUnbondRedelegateSlashTwice(t *testing.T) {
// slash the validator for an infraction committed after the unbonding and redelegation begin // slash the validator for an infraction committed after the unbonding and redelegation begin
ctx = ctx.WithBlockHeight(3) ctx = ctx.WithBlockHeight(3)
keeper.Slash(ctx, keep.PKs[0], 2, 10, sdk.NewDecWithPrec(5, 1)) keeper.Slash(ctx, consAddr0, 2, 10, sdk.NewDecWithPrec(5, 1))
// unbonding delegation should be unchanged // unbonding delegation should be unchanged
unbonding, found = keeper.GetUnbondingDelegation(ctx, del, valA) unbonding, found = keeper.GetUnbondingDelegation(ctx, del, valA)

View File

@ -66,6 +66,12 @@ func (k Keeper) SetDelegation(ctx sdk.Context, delegation types.Delegation) {
// remove a delegation from store // remove a delegation from store
func (k Keeper) RemoveDelegation(ctx sdk.Context, delegation types.Delegation) { func (k Keeper) RemoveDelegation(ctx sdk.Context, delegation types.Delegation) {
// call the hook if present
if k.hooks != nil {
k.hooks.OnDelegationRemoved(ctx, delegation.DelegatorAddr, delegation.ValidatorAddr)
}
store := ctx.KVStore(k.storeKey) store := ctx.KVStore(k.storeKey)
store.Delete(GetDelegationKey(delegation.DelegatorAddr, delegation.ValidatorAddr)) store.Delete(GetDelegationKey(delegation.DelegatorAddr, delegation.ValidatorAddr))
} }
@ -275,6 +281,11 @@ func (k Keeper) Delegate(ctx sdk.Context, delAddr sdk.AccAddress, bondAmt sdk.Co
k.SetDelegation(ctx, delegation) k.SetDelegation(ctx, delegation)
k.UpdateValidator(ctx, validator) k.UpdateValidator(ctx, validator)
// call the hook if present
if k.hooks != nil {
k.hooks.OnDelegationSharesModified(ctx, delegation.DelegatorAddr, validator.OperatorAddr)
}
return return
} }
@ -333,6 +344,11 @@ func (k Keeper) unbond(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValA
k.RemoveValidator(ctx, validator.OperatorAddr) k.RemoveValidator(ctx, validator.OperatorAddr)
} }
// call the hook if present
if k.hooks != nil {
k.hooks.OnDelegationSharesModified(ctx, delegation.DelegatorAddr, validator.OperatorAddr)
}
return amount, nil return amount, nil
} }

54
x/stake/keeper/hooks.go Normal file
View File

@ -0,0 +1,54 @@
//nolint
package keeper
import (
sdk "github.com/cosmos/cosmos-sdk/types"
)
// Expose the hooks if present
func (k Keeper) OnValidatorCreated(ctx sdk.Context, address sdk.ValAddress) {
if k.hooks != nil {
k.hooks.OnValidatorCreated(ctx, address)
}
}
func (k Keeper) OnValidatorCommissionChange(ctx sdk.Context, address sdk.ValAddress) {
if k.hooks != nil {
k.hooks.OnValidatorCommissionChange(ctx, address)
}
}
func (k Keeper) OnValidatorRemoved(ctx sdk.Context, address sdk.ValAddress) {
if k.hooks != nil {
k.hooks.OnValidatorRemoved(ctx, address)
}
}
func (k Keeper) OnValidatorBonded(ctx sdk.Context, address sdk.ConsAddress) {
if k.hooks != nil {
k.hooks.OnValidatorBonded(ctx, address)
}
}
func (k Keeper) OnValidatorBeginUnbonding(ctx sdk.Context, address sdk.ConsAddress) {
if k.hooks != nil {
k.hooks.OnValidatorBeginUnbonding(ctx, address)
}
}
func (k Keeper) OnDelegationCreated(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
if k.hooks != nil {
k.hooks.OnDelegationCreated(ctx, delAddr, valAddr)
}
}
func (k Keeper) OnDelegationSharesModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
if k.hooks != nil {
k.hooks.OnDelegationSharesModified(ctx, delAddr, valAddr)
}
}
func (k Keeper) OnDelegationRemoved(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
if k.hooks != nil {
k.hooks.OnDelegationRemoved(ctx, delAddr, valAddr)
}
}

View File

@ -10,11 +10,11 @@ import (
// keeper of the stake store // keeper of the stake store
type Keeper struct { type Keeper struct {
storeKey sdk.StoreKey storeKey sdk.StoreKey
storeTKey sdk.StoreKey storeTKey sdk.StoreKey
cdc *codec.Codec cdc *codec.Codec
bankKeeper bank.Keeper bankKeeper bank.Keeper
validatorHooks sdk.ValidatorHooks hooks sdk.StakingHooks
// codespace // codespace
codespace sdk.CodespaceType codespace sdk.CodespaceType
@ -22,22 +22,22 @@ type Keeper struct {
func NewKeeper(cdc *codec.Codec, key, tkey sdk.StoreKey, ck bank.Keeper, codespace sdk.CodespaceType) Keeper { func NewKeeper(cdc *codec.Codec, key, tkey sdk.StoreKey, ck bank.Keeper, codespace sdk.CodespaceType) Keeper {
keeper := Keeper{ keeper := Keeper{
storeKey: key, storeKey: key,
storeTKey: tkey, storeTKey: tkey,
cdc: cdc, cdc: cdc,
bankKeeper: ck, bankKeeper: ck,
validatorHooks: nil, hooks: nil,
codespace: codespace, codespace: codespace,
} }
return keeper return keeper
} }
// Set the validator hooks // Set the validator hooks
func (k Keeper) WithValidatorHooks(v sdk.ValidatorHooks) Keeper { func (k Keeper) WithHooks(sh sdk.StakingHooks) Keeper {
if k.validatorHooks != nil { if k.hooks != nil {
panic("cannot set validator hooks twice") panic("cannot set validator hooks twice")
} }
k.validatorHooks = v k.hooks = sh
return k return k
} }

View File

@ -3,8 +3,6 @@ package keeper
import ( import (
"encoding/binary" "encoding/binary"
"github.com/tendermint/tendermint/crypto"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/stake/types" "github.com/cosmos/cosmos-sdk/x/stake/types"
) )
@ -17,7 +15,7 @@ var (
ParamKey = []byte{0x00} // key for parameters relating to staking ParamKey = []byte{0x00} // key for parameters relating to staking
PoolKey = []byte{0x01} // key for the staking pools PoolKey = []byte{0x01} // key for the staking pools
ValidatorsKey = []byte{0x02} // prefix for each key to a validator ValidatorsKey = []byte{0x02} // prefix for each key to a validator
ValidatorsByPubKeyIndexKey = []byte{0x03} // prefix for each key to a validator index, by pubkey ValidatorsByConsAddrKey = []byte{0x03} // prefix for each key to a validator index, by pubkey
ValidatorsBondedIndexKey = []byte{0x04} // prefix for each key to a validator index, for bonded validators ValidatorsBondedIndexKey = []byte{0x04} // prefix for each key to a validator index, for bonded validators
ValidatorsByPowerIndexKey = []byte{0x05} // prefix for each key to a validator index, sorted by power ValidatorsByPowerIndexKey = []byte{0x05} // prefix for each key to a validator index, sorted by power
ValidatorCliffIndexKey = []byte{0x06} // key for the validator index of the cliff validator ValidatorCliffIndexKey = []byte{0x06} // key for the validator index of the cliff validator
@ -44,8 +42,8 @@ func GetValidatorKey(operatorAddr sdk.ValAddress) []byte {
// gets the key for the validator with pubkey // gets the key for the validator with pubkey
// VALUE: validator operator address ([]byte) // VALUE: validator operator address ([]byte)
func GetValidatorByPubKeyIndexKey(pubkey crypto.PubKey) []byte { func GetValidatorByConsAddrKey(addr sdk.ConsAddress) []byte {
return append(ValidatorsByPubKeyIndexKey, pubkey.Bytes()...) return append(ValidatorsByConsAddrKey, addr.Bytes()...)
} }
// gets the key for the current validator group // gets the key for the current validator group

View File

@ -3,10 +3,9 @@ package keeper
import ( import (
"fmt" "fmt"
"github.com/tendermint/tendermint/crypto"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/stake/types" "github.com/cosmos/cosmos-sdk/x/stake/types"
"github.com/tendermint/tendermint/crypto"
) )
// Implements ValidatorSet // Implements ValidatorSet
@ -60,8 +59,17 @@ func (k Keeper) Validator(ctx sdk.Context, address sdk.ValAddress) sdk.Validator
} }
// get the sdk.validator for a particular pubkey // get the sdk.validator for a particular pubkey
func (k Keeper) ValidatorByPubKey(ctx sdk.Context, pubkey crypto.PubKey) sdk.Validator { func (k Keeper) ValidatorByConsAddr(ctx sdk.Context, addr sdk.ConsAddress) sdk.Validator {
val, found := k.GetValidatorByPubKey(ctx, pubkey) val, found := k.GetValidatorByConsAddr(ctx, addr)
if !found {
return nil
}
return val
}
// get the sdk.validator for a particular pubkey
func (k Keeper) ValidatorByConsPubKey(ctx sdk.Context, consPubKey crypto.PubKey) sdk.Validator {
val, found := k.GetValidatorByConsPubKey(ctx, consPubKey)
if !found { if !found {
return nil return nil
} }
@ -95,15 +103,16 @@ func (k Keeper) Delegation(ctx sdk.Context, addrDel sdk.AccAddress, addrVal sdk.
return bond return bond
} }
// iterate through the active validator set and perform the provided function // iterate through all of the delegations from a delegator
func (k Keeper) IterateDelegations(ctx sdk.Context, delAddr sdk.AccAddress, fn func(index int64, delegation sdk.Delegation) (stop bool)) { func (k Keeper) IterateDelegations(ctx sdk.Context, delAddr sdk.AccAddress,
fn func(index int64, del sdk.Delegation) (stop bool)) {
store := ctx.KVStore(k.storeKey) store := ctx.KVStore(k.storeKey)
key := GetDelegationsKey(delAddr) delegatorPrefixKey := GetDelegationsKey(delAddr)
iterator := sdk.KVStorePrefixIterator(store, key) iterator := sdk.KVStorePrefixIterator(store, delegatorPrefixKey) //smallest to largest
i := int64(0) for i := int64(0); iterator.Valid(); iterator.Next() {
for ; iterator.Valid(); iterator.Next() { del := types.MustUnmarshalDelegation(k.cdc, iterator.Key(), iterator.Value())
delegation := types.MustUnmarshalDelegation(k.cdc, iterator.Key(), iterator.Value()) stop := fn(i, del)
stop := fn(i, delegation) // XXX is this safe will the fields be able to get written to?
if stop { if stop {
break break
} }

View File

@ -5,7 +5,6 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
types "github.com/cosmos/cosmos-sdk/x/stake/types" types "github.com/cosmos/cosmos-sdk/x/stake/types"
"github.com/tendermint/tendermint/crypto"
) )
// Slash a validator for an infraction committed at a known height // Slash a validator for an infraction committed at a known height
@ -24,7 +23,7 @@ import (
// not at a height in the future // not at a height in the future
// //
// nolint: gocyclo // nolint: gocyclo
func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight int64, power int64, slashFactor sdk.Dec) { func (k Keeper) Slash(ctx sdk.Context, consAddr sdk.ConsAddress, infractionHeight int64, power int64, slashFactor sdk.Dec) {
logger := ctx.Logger().With("module", "x/stake") logger := ctx.Logger().With("module", "x/stake")
if slashFactor.LT(sdk.ZeroDec()) { if slashFactor.LT(sdk.ZeroDec()) {
@ -36,7 +35,7 @@ func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight in
// ref https://github.com/cosmos/cosmos-sdk/issues/1348 // ref https://github.com/cosmos/cosmos-sdk/issues/1348
// ref https://github.com/cosmos/cosmos-sdk/issues/1471 // ref https://github.com/cosmos/cosmos-sdk/issues/1471
validator, found := k.GetValidatorByPubKey(ctx, pubkey) validator, found := k.GetValidatorByConsAddr(ctx, consAddr)
if !found { if !found {
// If not found, the validator must have been overslashed and removed - so we don't need to do anything // If not found, the validator must have been overslashed and removed - so we don't need to do anything
// NOTE: Correctness dependent on invariant that unbonding delegations / redelegations must also have been completely // NOTE: Correctness dependent on invariant that unbonding delegations / redelegations must also have been completely
@ -44,7 +43,7 @@ func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight in
// Log the slash attempt for future reference (maybe we should tag it too) // Log the slash attempt for future reference (maybe we should tag it too)
logger.Error(fmt.Sprintf( logger.Error(fmt.Sprintf(
"WARNING: Ignored attempt to slash a nonexistent validator with address %s, we recommend you investigate immediately", "WARNING: Ignored attempt to slash a nonexistent validator with address %s, we recommend you investigate immediately",
pubkey.Address())) consAddr))
return return
} }
@ -125,36 +124,28 @@ func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight in
} }
// jail a validator // jail a validator
func (k Keeper) Jail(ctx sdk.Context, pubkey crypto.PubKey) { func (k Keeper) Jail(ctx sdk.Context, consAddr sdk.ConsAddress) {
k.setJailed(ctx, pubkey, true) k.setJailed(ctx, consAddr, true)
validatorAddr, err := sdk.ValAddressFromHex(pubkey.Address().String())
if err != nil {
panic(err.Error())
}
logger := ctx.Logger().With("module", "x/stake") logger := ctx.Logger().With("module", "x/stake")
logger.Info(fmt.Sprintf("validator %s jailed", validatorAddr)) logger.Info(fmt.Sprintf("validator %s jailed", consAddr))
// TODO Return event(s), blocked on https://github.com/tendermint/tendermint/pull/1803 // TODO Return event(s), blocked on https://github.com/tendermint/tendermint/pull/1803
return return
} }
// unjail a validator // unjail a validator
func (k Keeper) Unjail(ctx sdk.Context, pubkey crypto.PubKey) { func (k Keeper) Unjail(ctx sdk.Context, consAddr sdk.ConsAddress) {
k.setJailed(ctx, pubkey, false) k.setJailed(ctx, consAddr, false)
validatorAddr, err := sdk.ValAddressFromHex(pubkey.Address().String())
if err != nil {
panic(err.Error())
}
logger := ctx.Logger().With("module", "x/stake") logger := ctx.Logger().With("module", "x/stake")
logger.Info(fmt.Sprintf("validator %s unjailed", validatorAddr)) logger.Info(fmt.Sprintf("validator %s unjailed", consAddr))
// TODO Return event(s), blocked on https://github.com/tendermint/tendermint/pull/1803 // TODO Return event(s), blocked on https://github.com/tendermint/tendermint/pull/1803
return return
} }
// set the jailed flag on a validator // set the jailed flag on a validator
func (k Keeper) setJailed(ctx sdk.Context, pubkey crypto.PubKey, isJailed bool) { func (k Keeper) setJailed(ctx sdk.Context, consAddr sdk.ConsAddress, isJailed bool) {
validator, found := k.GetValidatorByPubKey(ctx, pubkey) validator, found := k.GetValidatorByConsAddr(ctx, sdk.ConsAddress(consAddr))
if !found { if !found {
panic(fmt.Errorf("validator with pubkey %s not found, cannot set jailed to %v", pubkey, isJailed)) panic(fmt.Errorf("validator with consensus-Address %s not found, cannot set jailed to %v", consAddr, isJailed))
} }
validator.Jailed = isJailed validator.Jailed = isJailed
k.UpdateValidator(ctx, validator) // update validator, possibly unbonding or bonding it k.UpdateValidator(ctx, validator) // update validator, possibly unbonding or bonding it

View File

@ -27,7 +27,7 @@ func setupHelper(t *testing.T, amt int64) (sdk.Context, Keeper, types.Params) {
validator, pool, _ = validator.AddTokensFromDel(pool, sdk.NewInt(amt)) validator, pool, _ = validator.AddTokensFromDel(pool, sdk.NewInt(amt))
keeper.SetPool(ctx, pool) keeper.SetPool(ctx, pool)
validator = keeper.UpdateValidator(ctx, validator) validator = keeper.UpdateValidator(ctx, validator)
keeper.SetValidatorByPubKeyIndex(ctx, validator) keeper.SetValidatorByConsAddr(ctx, validator)
} }
pool = keeper.GetPool(ctx) pool = keeper.GetPool(ctx)
@ -42,7 +42,7 @@ func TestRevocation(t *testing.T) {
// setup // setup
ctx, keeper, _ := setupHelper(t, 10) ctx, keeper, _ := setupHelper(t, 10)
addr := addrVals[0] addr := addrVals[0]
pk := PKs[0] consAddr := sdk.ConsAddress(PKs[0].Address())
// initial state // initial state
val, found := keeper.GetValidator(ctx, addr) val, found := keeper.GetValidator(ctx, addr)
@ -50,13 +50,13 @@ func TestRevocation(t *testing.T) {
require.False(t, val.GetJailed()) require.False(t, val.GetJailed())
// test jail // test jail
keeper.Jail(ctx, pk) keeper.Jail(ctx, consAddr)
val, found = keeper.GetValidator(ctx, addr) val, found = keeper.GetValidator(ctx, addr)
require.True(t, found) require.True(t, found)
require.True(t, val.GetJailed()) require.True(t, val.GetJailed())
// test unjail // test unjail
keeper.Unjail(ctx, pk) keeper.Unjail(ctx, consAddr)
val, found = keeper.GetValidator(ctx, addr) val, found = keeper.GetValidator(ctx, addr)
require.True(t, found) require.True(t, found)
require.False(t, val.GetJailed()) require.False(t, val.GetJailed())
@ -179,24 +179,24 @@ func TestSlashRedelegation(t *testing.T) {
// tests Slash at a future height (must panic) // tests Slash at a future height (must panic)
func TestSlashAtFutureHeight(t *testing.T) { func TestSlashAtFutureHeight(t *testing.T) {
ctx, keeper, _ := setupHelper(t, 10) ctx, keeper, _ := setupHelper(t, 10)
pk := PKs[0] consAddr := sdk.ConsAddress(PKs[0].Address())
fraction := sdk.NewDecWithPrec(5, 1) fraction := sdk.NewDecWithPrec(5, 1)
require.Panics(t, func() { keeper.Slash(ctx, pk, 1, 10, fraction) }) require.Panics(t, func() { keeper.Slash(ctx, consAddr, 1, 10, fraction) })
} }
// tests Slash at the current height // tests Slash at the current height
func TestSlashValidatorAtCurrentHeight(t *testing.T) { func TestSlashValidatorAtCurrentHeight(t *testing.T) {
ctx, keeper, _ := setupHelper(t, 10) ctx, keeper, _ := setupHelper(t, 10)
pk := PKs[0] consAddr := sdk.ConsAddress(PKs[0].Address())
fraction := sdk.NewDecWithPrec(5, 1) fraction := sdk.NewDecWithPrec(5, 1)
oldPool := keeper.GetPool(ctx) oldPool := keeper.GetPool(ctx)
validator, found := keeper.GetValidatorByPubKey(ctx, pk) validator, found := keeper.GetValidatorByConsAddr(ctx, consAddr)
require.True(t, found) require.True(t, found)
keeper.Slash(ctx, pk, ctx.BlockHeight(), 10, fraction) keeper.Slash(ctx, consAddr, ctx.BlockHeight(), 10, fraction)
// read updated state // read updated state
validator, found = keeper.GetValidatorByPubKey(ctx, pk) validator, found = keeper.GetValidatorByConsAddr(ctx, consAddr)
require.True(t, found) require.True(t, found)
newPool := keeper.GetPool(ctx) newPool := keeper.GetPool(ctx)
@ -209,7 +209,7 @@ func TestSlashValidatorAtCurrentHeight(t *testing.T) {
// tests Slash at a previous height with an unbonding delegation // tests Slash at a previous height with an unbonding delegation
func TestSlashWithUnbondingDelegation(t *testing.T) { func TestSlashWithUnbondingDelegation(t *testing.T) {
ctx, keeper, params := setupHelper(t, 10) ctx, keeper, params := setupHelper(t, 10)
pk := PKs[0] consAddr := sdk.ConsAddress(PKs[0].Address())
fraction := sdk.NewDecWithPrec(5, 1) fraction := sdk.NewDecWithPrec(5, 1)
// set an unbonding delegation // set an unbonding delegation
@ -227,9 +227,9 @@ func TestSlashWithUnbondingDelegation(t *testing.T) {
// slash validator for the first time // slash validator for the first time
ctx = ctx.WithBlockHeight(12) ctx = ctx.WithBlockHeight(12)
oldPool := keeper.GetPool(ctx) oldPool := keeper.GetPool(ctx)
validator, found := keeper.GetValidatorByPubKey(ctx, pk) validator, found := keeper.GetValidatorByConsAddr(ctx, consAddr)
require.True(t, found) require.True(t, found)
keeper.Slash(ctx, pk, 10, 10, fraction) keeper.Slash(ctx, consAddr, 10, 10, fraction)
// read updating unbonding delegation // read updating unbonding delegation
ubd, found = keeper.GetUnbondingDelegation(ctx, addrDels[0], addrVals[0]) ubd, found = keeper.GetUnbondingDelegation(ctx, addrDels[0], addrVals[0])
@ -241,7 +241,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) {
// bonded tokens burned // bonded tokens burned
require.Equal(t, int64(3), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64()) require.Equal(t, int64(3), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64())
// read updated validator // read updated validator
validator, found = keeper.GetValidatorByPubKey(ctx, pk) validator, found = keeper.GetValidatorByConsAddr(ctx, consAddr)
require.True(t, found) require.True(t, found)
// power decreased by 3 - 6 stake originally bonded at the time of infraction // power decreased by 3 - 6 stake originally bonded at the time of infraction
// was still bonded at the time of discovery and was slashed by half, 4 stake // was still bonded at the time of discovery and was slashed by half, 4 stake
@ -251,7 +251,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) {
// slash validator again // slash validator again
ctx = ctx.WithBlockHeight(13) ctx = ctx.WithBlockHeight(13)
keeper.Slash(ctx, pk, 9, 10, fraction) keeper.Slash(ctx, consAddr, 9, 10, fraction)
ubd, found = keeper.GetUnbondingDelegation(ctx, addrDels[0], addrVals[0]) ubd, found = keeper.GetUnbondingDelegation(ctx, addrDels[0], addrVals[0])
require.True(t, found) require.True(t, found)
// balance decreased again // balance decreased again
@ -261,7 +261,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) {
// bonded tokens burned again // bonded tokens burned again
require.Equal(t, int64(6), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64()) require.Equal(t, int64(6), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64())
// read updated validator // read updated validator
validator, found = keeper.GetValidatorByPubKey(ctx, pk) validator, found = keeper.GetValidatorByConsAddr(ctx, consAddr)
require.True(t, found) require.True(t, found)
// power decreased by 3 again // power decreased by 3 again
require.Equal(t, sdk.NewDec(4), validator.GetPower()) require.Equal(t, sdk.NewDec(4), validator.GetPower())
@ -271,7 +271,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) {
// on the unbonding delegation, but it will slash stake bonded since the infraction // on the unbonding delegation, but it will slash stake bonded since the infraction
// this may not be the desirable behaviour, ref https://github.com/cosmos/cosmos-sdk/issues/1440 // this may not be the desirable behaviour, ref https://github.com/cosmos/cosmos-sdk/issues/1440
ctx = ctx.WithBlockHeight(13) ctx = ctx.WithBlockHeight(13)
keeper.Slash(ctx, pk, 9, 10, fraction) keeper.Slash(ctx, consAddr, 9, 10, fraction)
ubd, found = keeper.GetUnbondingDelegation(ctx, addrDels[0], addrVals[0]) ubd, found = keeper.GetUnbondingDelegation(ctx, addrDels[0], addrVals[0])
require.True(t, found) require.True(t, found)
// balance unchanged // balance unchanged
@ -281,7 +281,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) {
// bonded tokens burned again // bonded tokens burned again
require.Equal(t, int64(9), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64()) require.Equal(t, int64(9), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64())
// read updated validator // read updated validator
validator, found = keeper.GetValidatorByPubKey(ctx, pk) validator, found = keeper.GetValidatorByConsAddr(ctx, consAddr)
require.True(t, found) require.True(t, found)
// power decreased by 3 again // power decreased by 3 again
require.Equal(t, sdk.NewDec(1), validator.GetPower()) require.Equal(t, sdk.NewDec(1), validator.GetPower())
@ -291,7 +291,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) {
// on the unbonding delegation, but it will slash stake bonded since the infraction // on the unbonding delegation, but it will slash stake bonded since the infraction
// this may not be the desirable behaviour, ref https://github.com/cosmos/cosmos-sdk/issues/1440 // this may not be the desirable behaviour, ref https://github.com/cosmos/cosmos-sdk/issues/1440
ctx = ctx.WithBlockHeight(13) ctx = ctx.WithBlockHeight(13)
keeper.Slash(ctx, pk, 9, 10, fraction) keeper.Slash(ctx, consAddr, 9, 10, fraction)
ubd, found = keeper.GetUnbondingDelegation(ctx, addrDels[0], addrVals[0]) ubd, found = keeper.GetUnbondingDelegation(ctx, addrDels[0], addrVals[0])
require.True(t, found) require.True(t, found)
// balance unchanged // balance unchanged
@ -303,14 +303,14 @@ func TestSlashWithUnbondingDelegation(t *testing.T) {
// read updated validator // read updated validator
// power decreased by 1 again, validator is out of stake // power decreased by 1 again, validator is out of stake
// ergo validator should have been removed from the store // ergo validator should have been removed from the store
_, found = keeper.GetValidatorByPubKey(ctx, pk) _, found = keeper.GetValidatorByConsAddr(ctx, consAddr)
require.False(t, found) require.False(t, found)
} }
// tests Slash at a previous height with a redelegation // tests Slash at a previous height with a redelegation
func TestSlashWithRedelegation(t *testing.T) { func TestSlashWithRedelegation(t *testing.T) {
ctx, keeper, params := setupHelper(t, 10) ctx, keeper, params := setupHelper(t, 10)
pk := PKs[0] consAddr := sdk.ConsAddress(PKs[0].Address())
fraction := sdk.NewDecWithPrec(5, 1) fraction := sdk.NewDecWithPrec(5, 1)
// set a redelegation // set a redelegation
@ -343,9 +343,9 @@ func TestSlashWithRedelegation(t *testing.T) {
// slash validator // slash validator
ctx = ctx.WithBlockHeight(12) ctx = ctx.WithBlockHeight(12)
oldPool := keeper.GetPool(ctx) oldPool := keeper.GetPool(ctx)
validator, found := keeper.GetValidatorByPubKey(ctx, pk) validator, found := keeper.GetValidatorByConsAddr(ctx, consAddr)
require.True(t, found) require.True(t, found)
keeper.Slash(ctx, pk, 10, 10, fraction) keeper.Slash(ctx, consAddr, 10, 10, fraction)
// read updating redelegation // read updating redelegation
rd, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) rd, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
@ -357,7 +357,7 @@ func TestSlashWithRedelegation(t *testing.T) {
// bonded tokens burned // bonded tokens burned
require.Equal(t, int64(5), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64()) require.Equal(t, int64(5), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64())
// read updated validator // read updated validator
validator, found = keeper.GetValidatorByPubKey(ctx, pk) validator, found = keeper.GetValidatorByConsAddr(ctx, consAddr)
require.True(t, found) require.True(t, found)
// power decreased by 2 - 4 stake originally bonded at the time of infraction // power decreased by 2 - 4 stake originally bonded at the time of infraction
// was still bonded at the time of discovery and was slashed by half, 4 stake // was still bonded at the time of discovery and was slashed by half, 4 stake
@ -367,9 +367,9 @@ func TestSlashWithRedelegation(t *testing.T) {
// slash the validator again // slash the validator again
ctx = ctx.WithBlockHeight(12) ctx = ctx.WithBlockHeight(12)
validator, found = keeper.GetValidatorByPubKey(ctx, pk) validator, found = keeper.GetValidatorByConsAddr(ctx, consAddr)
require.True(t, found) require.True(t, found)
require.NotPanics(t, func() { keeper.Slash(ctx, pk, 10, 10, sdk.OneDec()) }) require.NotPanics(t, func() { keeper.Slash(ctx, consAddr, 10, 10, sdk.OneDec()) })
// read updating redelegation // read updating redelegation
rd, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) rd, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
@ -381,16 +381,16 @@ func TestSlashWithRedelegation(t *testing.T) {
// seven bonded tokens burned // seven bonded tokens burned
require.Equal(t, int64(12), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64()) require.Equal(t, int64(12), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64())
// read updated validator // read updated validator
validator, found = keeper.GetValidatorByPubKey(ctx, pk) validator, found = keeper.GetValidatorByConsAddr(ctx, consAddr)
require.True(t, found) require.True(t, found)
// power decreased by 4 // power decreased by 4
require.Equal(t, sdk.NewDec(4), validator.GetPower()) require.Equal(t, sdk.NewDec(4), validator.GetPower())
// slash the validator again, by 100% // slash the validator again, by 100%
ctx = ctx.WithBlockHeight(12) ctx = ctx.WithBlockHeight(12)
validator, found = keeper.GetValidatorByPubKey(ctx, pk) validator, found = keeper.GetValidatorByConsAddr(ctx, consAddr)
require.True(t, found) require.True(t, found)
keeper.Slash(ctx, pk, 10, 10, sdk.OneDec()) keeper.Slash(ctx, consAddr, 10, 10, sdk.OneDec())
// read updating redelegation // read updating redelegation
rd, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) rd, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
@ -403,16 +403,16 @@ func TestSlashWithRedelegation(t *testing.T) {
require.Equal(t, int64(16), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64()) require.Equal(t, int64(16), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64())
// read updated validator // read updated validator
// validator decreased to zero power, should have been removed from the store // validator decreased to zero power, should have been removed from the store
_, found = keeper.GetValidatorByPubKey(ctx, pk) _, found = keeper.GetValidatorByConsAddr(ctx, consAddr)
require.False(t, found) require.False(t, found)
// slash the validator again, by 100% // slash the validator again, by 100%
// no stake remains to be slashed // no stake remains to be slashed
ctx = ctx.WithBlockHeight(12) ctx = ctx.WithBlockHeight(12)
// validator no longer in the store // validator no longer in the store
_, found = keeper.GetValidatorByPubKey(ctx, pk) _, found = keeper.GetValidatorByConsAddr(ctx, consAddr)
require.False(t, found) require.False(t, found)
keeper.Slash(ctx, pk, 10, 10, sdk.OneDec()) keeper.Slash(ctx, consAddr, 10, 10, sdk.OneDec())
// read updating redelegation // read updating redelegation
rd, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) rd, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
@ -425,7 +425,7 @@ func TestSlashWithRedelegation(t *testing.T) {
require.Equal(t, int64(16), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64()) require.Equal(t, int64(16), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64())
// read updated validator // read updated validator
// power still zero, still not in the store // power still zero, still not in the store
_, found = keeper.GetValidatorByPubKey(ctx, pk) _, found = keeper.GetValidatorByConsAddr(ctx, consAddr)
require.False(t, found) require.False(t, found)
} }
@ -472,9 +472,10 @@ func TestSlashBoth(t *testing.T) {
// slash validator // slash validator
ctx = ctx.WithBlockHeight(12) ctx = ctx.WithBlockHeight(12)
oldPool := keeper.GetPool(ctx) oldPool := keeper.GetPool(ctx)
validator, found := keeper.GetValidatorByPubKey(ctx, PKs[0]) validator, found := keeper.GetValidatorByConsPubKey(ctx, PKs[0])
require.True(t, found) require.True(t, found)
keeper.Slash(ctx, PKs[0], 10, 10, fraction) consAddr0 := sdk.ConsAddress(PKs[0].Address())
keeper.Slash(ctx, consAddr0, 10, 10, fraction)
// read updating redelegation // read updating redelegation
rdA, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) rdA, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
@ -488,7 +489,7 @@ func TestSlashBoth(t *testing.T) {
// bonded tokens burned // bonded tokens burned
require.Equal(t, int64(3), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64()) require.Equal(t, int64(3), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64())
// read updated validator // read updated validator
validator, found = keeper.GetValidatorByPubKey(ctx, PKs[0]) validator, found = keeper.GetValidatorByConsPubKey(ctx, PKs[0])
require.True(t, found) require.True(t, found)
// power not decreased, all stake was bonded since // power not decreased, all stake was bonded since
require.Equal(t, sdk.NewDec(10), validator.GetPower()) require.Equal(t, sdk.NewDec(10), validator.GetPower())

View File

@ -58,14 +58,25 @@ func (k Keeper) GetValidator(ctx sdk.Context, addr sdk.ValAddress) (validator ty
return validator, true return validator, true
} }
// get a single validator by pubkey // get a single validator by consensus address
func (k Keeper) GetValidatorByPubKey(ctx sdk.Context, pubkey crypto.PubKey) (validator types.Validator, found bool) { func (k Keeper) GetValidatorByConsAddr(ctx sdk.Context, consAddr sdk.ConsAddress) (validator types.Validator, found bool) {
store := ctx.KVStore(k.storeKey) store := ctx.KVStore(k.storeKey)
addr := store.Get(GetValidatorByPubKeyIndexKey(pubkey)) opAddr := store.Get(GetValidatorByConsAddrKey(consAddr))
if addr == nil { if opAddr == nil {
return validator, false return validator, false
} }
return k.GetValidator(ctx, addr) return k.GetValidator(ctx, opAddr)
}
// get a single validator by pubkey
func (k Keeper) GetValidatorByConsPubKey(ctx sdk.Context, consPubKey crypto.PubKey) (validator types.Validator, found bool) {
store := ctx.KVStore(k.storeKey)
consAddr := sdk.ConsAddress(consPubKey.Address())
opAddr := store.Get(GetValidatorByConsAddrKey(consAddr))
if opAddr == nil {
return validator, false
}
return k.GetValidator(ctx, opAddr)
} }
// set the main record holding validator details // set the main record holding validator details
@ -76,9 +87,11 @@ func (k Keeper) SetValidator(ctx sdk.Context, validator types.Validator) {
} }
// validator index // validator index
func (k Keeper) SetValidatorByPubKeyIndex(ctx sdk.Context, validator types.Validator) { // TODO change to SetValidatorByConsAddr? used for retrieving from ConsPubkey as well- kinda confusing
func (k Keeper) SetValidatorByConsAddr(ctx sdk.Context, validator types.Validator) {
store := ctx.KVStore(k.storeKey) store := ctx.KVStore(k.storeKey)
store.Set(GetValidatorByPubKeyIndexKey(validator.ConsPubKey), validator.OperatorAddr) consAddr := sdk.ConsAddress(validator.OperatorAddr.Bytes())
store.Set(GetValidatorByConsAddrKey(consAddr), validator.OperatorAddr)
} }
// validator index // validator index
@ -622,8 +635,8 @@ func (k Keeper) beginUnbondingValidator(ctx sdk.Context, validator types.Validat
store.Delete(GetValidatorsBondedIndexKey(validator.OperatorAddr)) store.Delete(GetValidatorsBondedIndexKey(validator.OperatorAddr))
// call the unbond hook if present // call the unbond hook if present
if k.validatorHooks != nil { if k.hooks != nil {
k.validatorHooks.OnValidatorBeginUnbonding(ctx, validator.ConsAddress()) k.hooks.OnValidatorBeginUnbonding(ctx, validator.ConsAddress())
} }
// return updated validator // return updated validator
@ -657,8 +670,8 @@ func (k Keeper) bondValidator(ctx sdk.Context, validator types.Validator) types.
tstore.Set(GetTendermintUpdatesTKey(validator.OperatorAddr), bzABCI) tstore.Set(GetTendermintUpdatesTKey(validator.OperatorAddr), bzABCI)
// call the bond hook if present // call the bond hook if present
if k.validatorHooks != nil { if k.hooks != nil {
k.validatorHooks.OnValidatorBonded(ctx, validator.ConsAddress()) k.hooks.OnValidatorBonded(ctx, validator.ConsAddress())
} }
// return updated validator // return updated validator
@ -668,6 +681,11 @@ func (k Keeper) bondValidator(ctx sdk.Context, validator types.Validator) types.
// remove the validator record and associated indexes // remove the validator record and associated indexes
func (k Keeper) RemoveValidator(ctx sdk.Context, address sdk.ValAddress) { func (k Keeper) RemoveValidator(ctx sdk.Context, address sdk.ValAddress) {
// call the hook if present
if k.hooks != nil {
k.hooks.OnValidatorRemoved(ctx, address)
}
// first retrieve the old validator record // first retrieve the old validator record
validator, found := k.GetValidator(ctx, address) validator, found := k.GetValidator(ctx, address)
if !found { if !found {
@ -678,7 +696,7 @@ func (k Keeper) RemoveValidator(ctx sdk.Context, address sdk.ValAddress) {
store := ctx.KVStore(k.storeKey) store := ctx.KVStore(k.storeKey)
pool := k.GetPool(ctx) pool := k.GetPool(ctx)
store.Delete(GetValidatorKey(address)) store.Delete(GetValidatorKey(address))
store.Delete(GetValidatorByPubKeyIndexKey(validator.ConsPubKey)) store.Delete(GetValidatorByConsAddrKey(sdk.ConsAddress(validator.ConsPubKey.Address())))
store.Delete(GetValidatorsByPowerIndexKey(validator, pool)) store.Delete(GetValidatorsByPowerIndexKey(validator, pool))
// delete from the current and power weighted validator groups if the validator // delete from the current and power weighted validator groups if the validator
@ -727,3 +745,36 @@ func ensureValidatorFound(found bool, ownerAddr []byte) {
panic(fmt.Sprintf("validator record not found for address: %X\n", ownerAddr)) panic(fmt.Sprintf("validator record not found for address: %X\n", ownerAddr))
} }
} }
//__________________________________________________________________________
// XXX remove this code - this is should be superceded by commission work that bez is doing
// get a single validator
func (k Keeper) UpdateValidatorCommission(ctx sdk.Context, addr sdk.ValAddress, newCommission sdk.Dec) sdk.Error {
// call the hook if present
if k.hooks != nil {
k.hooks.OnValidatorCommissionChange(ctx, addr)
}
validator, found := k.GetValidator(ctx, addr)
// check for errors
switch {
case !found:
return types.ErrNoValidatorFound(k.Codespace())
case newCommission.LT(sdk.ZeroDec()):
return types.ErrCommissionNegative(k.Codespace())
case newCommission.GT(validator.CommissionMax):
return types.ErrCommissionBeyondMax(k.Codespace())
//case rateChange(Commission) > CommissionMaxChange: // XXX XXX XXX TODO implementation
//return types.ErrCommissionPastRate(k.Codespace())
}
// TODO adjust all the commission terms appropriately
validator.Commission = newCommission
k.SetValidator(ctx, validator)
return nil
}

View File

@ -260,12 +260,13 @@ func TestSlashToZeroPowerRemoved(t *testing.T) {
require.Equal(t, sdk.Unbonded, validator.Status) require.Equal(t, sdk.Unbonded, validator.Status)
require.Equal(t, int64(100), validator.Tokens.RoundInt64()) require.Equal(t, int64(100), validator.Tokens.RoundInt64())
keeper.SetPool(ctx, pool) keeper.SetPool(ctx, pool)
keeper.SetValidatorByPubKeyIndex(ctx, validator) keeper.SetValidatorByConsAddr(ctx, validator)
validator = keeper.UpdateValidator(ctx, validator) validator = keeper.UpdateValidator(ctx, validator)
require.Equal(t, int64(100), validator.Tokens.RoundInt64(), "\nvalidator %v\npool %v", validator, pool) require.Equal(t, int64(100), validator.Tokens.RoundInt64(), "\nvalidator %v\npool %v", validator, pool)
// slash the validator by 100% // slash the validator by 100%
keeper.Slash(ctx, PKs[0], 0, 100, sdk.OneDec()) consAddr0 := sdk.ConsAddress(PKs[0].Address())
keeper.Slash(ctx, consAddr0, 0, 100, sdk.OneDec())
// validator should have been deleted // validator should have been deleted
_, found := keeper.GetValidator(ctx, addrVals[0]) _, found := keeper.GetValidator(ctx, addrVals[0])
require.False(t, found) require.False(t, found)

View File

@ -35,7 +35,7 @@ var (
NewKeeper = keeper.NewKeeper NewKeeper = keeper.NewKeeper
GetValidatorKey = keeper.GetValidatorKey GetValidatorKey = keeper.GetValidatorKey
GetValidatorByPubKeyIndexKey = keeper.GetValidatorByPubKeyIndexKey GetValidatorByConsAddrKey = keeper.GetValidatorByConsAddrKey
GetValidatorsBondedIndexKey = keeper.GetValidatorsBondedIndexKey GetValidatorsBondedIndexKey = keeper.GetValidatorsBondedIndexKey
GetValidatorsByPowerIndexKey = keeper.GetValidatorsByPowerIndexKey GetValidatorsByPowerIndexKey = keeper.GetValidatorsByPowerIndexKey
GetTendermintUpdatesTKey = keeper.GetTendermintUpdatesTKey GetTendermintUpdatesTKey = keeper.GetTendermintUpdatesTKey
@ -44,7 +44,7 @@ var (
ParamKey = keeper.ParamKey ParamKey = keeper.ParamKey
PoolKey = keeper.PoolKey PoolKey = keeper.PoolKey
ValidatorsKey = keeper.ValidatorsKey ValidatorsKey = keeper.ValidatorsKey
ValidatorsByPubKeyIndexKey = keeper.ValidatorsByPubKeyIndexKey ValidatorsByConsAddrKey = keeper.ValidatorsByConsAddrKey
ValidatorsBondedIndexKey = keeper.ValidatorsBondedIndexKey ValidatorsBondedIndexKey = keeper.ValidatorsBondedIndexKey
ValidatorsByPowerIndexKey = keeper.ValidatorsByPowerIndexKey ValidatorsByPowerIndexKey = keeper.ValidatorsByPowerIndexKey
ValidatorCliffIndexKey = keeper.ValidatorCliffIndexKey ValidatorCliffIndexKey = keeper.ValidatorCliffIndexKey

View File

@ -22,6 +22,5 @@ func init() {
cdc := codec.New() cdc := codec.New()
RegisterCodec(cdc) RegisterCodec(cdc)
codec.RegisterCrypto(cdc) codec.RegisterCrypto(cdc)
MsgCdc = cdc MsgCdc = cdc.Seal()
//MsgCdc = cdc.Seal() //TODO use when upgraded to go-amino 0.9.10
} }

View File

@ -89,7 +89,7 @@ var _ sdk.Delegation = Delegation{}
// nolint - for sdk.Delegation // nolint - for sdk.Delegation
func (d Delegation) GetDelegator() sdk.AccAddress { return d.DelegatorAddr } func (d Delegation) GetDelegator() sdk.AccAddress { return d.DelegatorAddr }
func (d Delegation) GetValidator() sdk.ValAddress { return d.ValidatorAddr } func (d Delegation) GetValidator() sdk.ValAddress { return d.ValidatorAddr }
func (d Delegation) GetBondShares() sdk.Dec { return d.Shares } func (d Delegation) GetShares() sdk.Dec { return d.Shares }
// HumanReadableString returns a human readable string representation of a // HumanReadableString returns a human readable string representation of a
// Delegation. An error is returned if the Delegation's delegator or validator // Delegation. An error is returned if the Delegation's delegator or validator

View File

@ -65,6 +65,14 @@ func ErrCommissionHuge(codespace sdk.CodespaceType) sdk.Error {
return sdk.NewError(codespace, CodeInvalidValidator, "commission cannot be more than 100%") return sdk.NewError(codespace, CodeInvalidValidator, "commission cannot be more than 100%")
} }
func ErrCommissionBeyondMax(codespace sdk.CodespaceType) sdk.Error {
return sdk.NewError(codespace, CodeInvalidValidator, "commission cannot be more than preset commission maximum")
}
func ErrCommissionPastRate(codespace sdk.CodespaceType) sdk.Error {
return sdk.NewError(codespace, CodeInvalidValidator, "commission change is greater than the commission rate, please wait before changing your commission more")
}
func ErrNilDelegatorAddr(codespace sdk.CodespaceType) sdk.Error { func ErrNilDelegatorAddr(codespace sdk.CodespaceType) sdk.Error {
return sdk.NewError(codespace, CodeInvalidInput, "delegator address is nil") return sdk.NewError(codespace, CodeInvalidInput, "delegator address is nil")
} }

View File

@ -470,12 +470,14 @@ func (v Validator) IsUnbonded(ctx sdk.Context) bool {
var _ sdk.Validator = Validator{} var _ sdk.Validator = Validator{}
// nolint - for sdk.Validator // nolint - for sdk.Validator
func (v Validator) GetJailed() bool { return v.Jailed } func (v Validator) GetJailed() bool { return v.Jailed }
func (v Validator) GetMoniker() string { return v.Description.Moniker } func (v Validator) GetMoniker() string { return v.Description.Moniker }
func (v Validator) GetStatus() sdk.BondStatus { return v.Status } func (v Validator) GetStatus() sdk.BondStatus { return v.Status }
func (v Validator) GetOperator() sdk.ValAddress { return v.OperatorAddr } func (v Validator) GetOperator() sdk.ValAddress { return v.OperatorAddr }
func (v Validator) GetPubKey() crypto.PubKey { return v.ConsPubKey } func (v Validator) GetPubKey() crypto.PubKey { return v.ConsPubKey }
func (v Validator) GetPower() sdk.Dec { return v.BondedTokens() } func (v Validator) GetConsAddr() sdk.ConsAddress { return sdk.ConsAddress(v.ConsPubKey.Address()) }
func (v Validator) GetTokens() sdk.Dec { return v.Tokens } func (v Validator) GetPower() sdk.Dec { return v.BondedTokens() }
func (v Validator) GetDelegatorShares() sdk.Dec { return v.DelegatorShares } func (v Validator) GetTokens() sdk.Dec { return v.Tokens }
func (v Validator) GetBondHeight() int64 { return v.BondHeight } func (v Validator) GetCommission() sdk.Dec { return v.Commission }
func (v Validator) GetDelegatorShares() sdk.Dec { return v.DelegatorShares }
func (v Validator) GetBondHeight() int64 { return v.BondHeight }