diff --git a/x/stake/keeper.go b/x/stake/keeper.go index 4fe7574c1..a25ec848c 100644 --- a/x/stake/keeper.go +++ b/x/stake/keeper.go @@ -227,7 +227,8 @@ func (k Keeper) updateValidator(ctx sdk.Context, validator Validator) Validator if oldFound { store.Delete(GetValidatorsByPowerKey(oldValidator, pool)) } - store.Set(GetValidatorsByPowerKey(validator, pool), validator.Owner) + valPower := GetValidatorsByPowerKey(validator, pool) + store.Set(valPower, validator.Owner) // efficiency case: // if already bonded and power increasing only need to update tendermint @@ -237,8 +238,14 @@ func (k Keeper) updateValidator(ctx sdk.Context, validator Validator) Validator return validator } - // TODO efficiency case: + // efficiency case: // if was unbonded/or is a new validator - and the new power is less than the cliff validator + cliffPower := k.getCliffValidatorPower(ctx) + if cliffPower != nil && + (!oldFound || (oldFound && oldValidator.Status() == sdk.Unbonded)) && + bytes.Compare(valPower, cliffPower) == -1 { //(valPower < cliffPower + return validator + } // update the validator set for this validator updatedVal := k.updateBondedValidatorsNew(ctx, store, validator) @@ -282,8 +289,13 @@ func (k Keeper) updateBondedValidatorsNew(ctx sdk.Context, store sdk.KVStore, maxValidators := k.GetParams(ctx).MaxValidators iterator = store.ReverseSubspaceIterator(ValidatorsByPowerKey) // largest to smallest i := 0 + var validator Validator for ; ; i++ { if !iterator.Valid() || i > int(maxValidators-1) { + + if i-1 == int(maxValidators-1) { + k.setCliffValidatorPower(ctx, validator, k.GetPool(ctx)) + } iterator.Close() break } @@ -293,7 +305,6 @@ func (k Keeper) updateBondedValidatorsNew(ctx sdk.Context, store sdk.KVStore, // use the validator provided because it has not yet been updated // in the main validator store ownerAddr := iterator.Value() - var validator Validator if bytes.Equal(ownerAddr, newValidator.Owner) { validator = newValidator } else { @@ -562,6 +573,21 @@ func (k Keeper) setIntraTxCounter(ctx sdk.Context, counter int16) { //__________________________________________________________________________ +// get the current power of the validator on the cliff +func (k Keeper) getCliffValidatorPower(ctx sdk.Context) []byte { + store := ctx.KVStore(k.storeKey) + return store.Get(ValidatorCliffKey) +} + +// set the current power of the validator on the cliff +func (k Keeper) setCliffValidatorPower(ctx sdk.Context, validator Validator, pool Pool) { + store := ctx.KVStore(k.storeKey) + bz := GetValidatorsByPowerKey(validator, pool) + store.Set(ValidatorCliffKey, bz) +} + +//__________________________________________________________________________ + // Implements ValidatorSet var _ sdk.ValidatorSet = Keeper{} diff --git a/x/stake/keeper_keys.go b/x/stake/keeper_keys.go index c66f65a15..a2ad0f252 100644 --- a/x/stake/keeper_keys.go +++ b/x/stake/keeper_keys.go @@ -18,9 +18,10 @@ var ( 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 - TendermintUpdatesKey = []byte{0x05} // prefix for each key to a validator which is being updated - DelegationKey = []byte{0x06} // prefix for each key to a delegator's bond - IntraTxCounterKey = []byte{0x07} // key for block-local tx index + ValidatorCliffKey = []byte{0x05} // key for block-local tx index + TendermintUpdatesKey = []byte{0x06} // prefix for each key to a validator which is being updated + DelegationKey = []byte{0x07} // prefix for each key to a delegator's bond + IntraTxCounterKey = []byte{0x08} // key for block-local tx index ) const maxDigitsForAccount = 12 // ~220,000,000 atoms created at launch @@ -51,7 +52,7 @@ func GetValidatorsByPowerKey(validator Validator, pool Pool) []byte { return append(ValidatorsByPowerKey, append(powerBytes, append(heightBytes, - append(counterBytes, validator.Owner.Bytes()...)...)...)...) + append(counterBytes, validator.Owner.Bytes()...)...)...)...) // TODO don't technically need to store owner } // get the key for the accumulated update validators