Skip to content

Commit

Permalink
refactor(x/staking): use sdk validator updates
Browse files Browse the repository at this point in the history
  • Loading branch information
julienrbrt committed Mar 19, 2024
1 parent bfa734c commit 100f280
Show file tree
Hide file tree
Showing 11 changed files with 109 additions and 128 deletions.
3 changes: 3 additions & 0 deletions core/appmodule/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ type HasEndBlocker = appmodule.HasEndBlocker
// HasRegisterInterfaces is the interface for modules to register their msg types.
type HasRegisterInterfaces = appmodule.HasRegisterInterfaces

// ValidatorUpdate defines a validator update.
type ValidatorUpdate = appmodule.ValidatorUpdate

// HasServices is the extension interface that modules should implement to register
// implementations of services defined in .proto files.
type HasServices interface {
Expand Down
5 changes: 2 additions & 3 deletions tests/integration/staking/keeper/genesis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import (
"fmt"
"testing"

abci "github.com/cometbft/cometbft/abci/types"
"github.com/stretchr/testify/require"
"gotest.tools/v3/assert"

"cosmossdk.io/core/appmodule"
"cosmossdk.io/math"
banktestutil "cosmossdk.io/x/bank/testutil"
"cosmossdk.io/x/staking"
Expand Down Expand Up @@ -128,8 +128,7 @@ func TestInitGenesis(t *testing.T) {
assert.Assert(t, found)
assert.Equal(t, types.Bonded, resVal.Status)

abcivals := make([]abci.ValidatorUpdate, len(vals))
validatorUpdates := make([]module.ValidatorUpdate, len(abcivals))
validatorUpdates := make([]appmodule.ValidatorUpdate, len(vals))
for i, val := range validators {
validatorUpdates[i] = val.ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx))
}
Expand Down
52 changes: 26 additions & 26 deletions x/staking/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,60 +43,60 @@ Ref: https://keepachangelog.com/en/1.0.0/

### API Breaking Changes

* [#19754](https://github.com/cosmos/cosmos-sdk/pull/19754) update to use `[]appmodule.ValidatorUpdate` as return for `ApplyAndReturnValidatorSetUpdates`.
* [#19414](https://github.com/cosmos/cosmos-sdk/pull/19414) Staking module takes an environment variable in `NewStakingKeeper` instead of individual services.
* [#19742](https://github.com/cosmos/cosmos-sdk/pull/19742) `NewStakeAuthorization` now takes `address.Codec` as argument.
* [#19735](https://github.com/cosmos/cosmos-sdk/pull/19735) Update genesis api to match new `appmodule.HasGenesis` interface.
* [#18198](https://github.com/cosmos/cosmos-sdk/pull/18198) `Validator` and `Delegator` interfaces were moved to `github.com/cosmos/cosmos-sdk/types` to avoid interface dependency on staking in other modules.
* [#17778](https://github.com/cosmos/cosmos-sdk/pull/17778) Use collections for `Params`
* remove from `Keeper`: `GetParams`, `SetParams`
* remove from `Keeper`: `GetParams`, `SetParams`
* [#17486](https://github.com/cosmos/cosmos-sdk/pull/17486) Use collections for `RedelegationQueueKey`:
* remove from `types`: `GetRedelegationTimeKey`
* remove from `Keeper`: `RedelegationQueueIterator`
* remove from `types`: `GetRedelegationTimeKey`
* remove from `Keeper`: `RedelegationQueueIterator`
* [#17562](https://github.com/cosmos/cosmos-sdk/pull/17562) Use collections for `ValidatorQueue`
* remove from `types`: `GetValidatorQueueKey`, `ParseValidatorQueueKey`
* remove from `Keeper`: `ValidatorQueueIterator`
* remove from `types`: `GetValidatorQueueKey`, `ParseValidatorQueueKey`
* remove from `Keeper`: `ValidatorQueueIterator`
* [#17498](https://github.com/cosmos/cosmos-sdk/pull/17498) Use collections for `LastValidatorPower`:
* remove from `types`: `GetLastValidatorPowerKey`
* remove from `Keeper`: `LastValidatorsIterator`, `IterateLastValidators`
* remove from `types`: `GetLastValidatorPowerKey`
* remove from `Keeper`: `LastValidatorsIterator`, `IterateLastValidators`
* [#17291](https://github.com/cosmos/cosmos-sdk/pull/17291) Use collections for `UnbondingDelegationByValIndex`:
* remove from `types`: `GetUBDKeyFromValIndexKey`, `GetUBDsByValIndexKey`, `GetUBDByValIndexKey`
* remove from `types`: `GetUBDKeyFromValIndexKey`, `GetUBDsByValIndexKey`, `GetUBDByValIndexKey`
* (x/slashing) [#17568](https://github.com/cosmos/cosmos-sdk/pull/17568) Use collections for `ValidatorMissedBlockBitmap`:
* remove from `types`: `ValidatorMissedBlockBitmapPrefixKey`, `ValidatorMissedBlockBitmapKey`
* remove from `types`: `ValidatorMissedBlockBitmapPrefixKey`, `ValidatorMissedBlockBitmapKey`
* [#17481](https://github.com/cosmos/cosmos-sdk/pull/17481) Use collections for `UnbondingQueue`:
* remove from `Keeper`: `UBDQueueIterator`
* remove from `types`: `GetUnbondingDelegationTimeKey`
* remove from `Keeper`: `UBDQueueIterator`
* remove from `types`: `GetUnbondingDelegationTimeKey`
* [#17123](https://github.com/cosmos/cosmos-sdk/pull/17123) Use collections for `Validators`
* [#17270](https://github.com/cosmos/cosmos-sdk/pull/17270) Use collections for `UnbondingDelegation`:
* remove from `types`: `GetUBDsKey`
* remove from `Keeper`: `IterateUnbondingDelegations`, `IterateDelegatorUnbondingDelegations`
* remove from `types`: `GetUBDsKey`
* remove from `Keeper`: `IterateUnbondingDelegations`, `IterateDelegatorUnbondingDelegations`
* [#17336](https://github.com/cosmos/cosmos-sdk/pull/17336) Use collections for `RedelegationByValDstIndexKey`:
* remove from `types`: `GetREDByValDstIndexKey`, `GetREDsToValDstIndexKey`
* remove from `types`: `GetREDByValDstIndexKey`, `GetREDsToValDstIndexKey`
* [#17332](https://github.com/cosmos/cosmos-sdk/pull/17332) Use collections for `RedelegationByValSrcIndexKey`:
* remove from `types`: `GetREDKeyFromValSrcIndexKey`, `GetREDsFromValSrcIndexKey`
* remove from `types`: `GetREDKeyFromValSrcIndexKey`, `GetREDsFromValSrcIndexKey`
* [#17315](https://github.com/cosmos/cosmos-sdk/pull/17315) Use collections for `RedelegationKey`:
* remove from `keeper`: `GetRedelegation`
* remove from `keeper`: `GetRedelegation`
* [#17260](https://github.com/cosmos/cosmos-sdk/pull/17260) Use collections for `DelegationKey`:
* remove from `types`: `GetDelegationKey`, `GetDelegationsKey`
* remove from `types`: `GetDelegationKey`, `GetDelegationsKey`
* [#17288](https://github.com/cosmos/cosmos-sdk/pull/17288) Use collections for `UnbondingIndex`:
* remove from `types`: `GetUnbondingIndexKey`.
* remove from `types`: `GetUnbondingIndexKey`.
* [#17256](https://github.com/cosmos/cosmos-sdk/pull/17256) Use collections for `UnbondingID`.
* [#17260](https://github.com/cosmos/cosmos-sdk/pull/17260) Use collections for `ValidatorByConsAddr`:
* remove from `types`: `GetValidatorByConsAddrKey`
* remove from `types`: `GetValidatorByConsAddrKey`
* [#17248](https://github.com/cosmos/cosmos-sdk/pull/17248) Use collections for `UnbondingType`.
* remove from `types`: `GetUnbondingTypeKey`.
* remove from `types`: `GetUnbondingTypeKey`.
* [#17063](https://github.com/cosmos/cosmos-sdk/pull/17063) Use collections for `HistoricalInfo`:
* remove `Keeper`: `GetHistoricalInfo`, `SetHistoricalInfo`
* remove `Keeper`: `GetHistoricalInfo`, `SetHistoricalInfo`
* [#17062](https://github.com/cosmos/cosmos-sdk/pull/17062) Use collections for `ValidatorUpdates`:
* remove `Keeper`: `SetValidatorUpdates`, `GetValidatorUpdates`
* remove `Keeper`: `SetValidatorUpdates`, `GetValidatorUpdates`
* [#17026](https://github.com/cosmos/cosmos-sdk/pull/17026) Use collections for `LastTotalPower`:
* remove `Keeper`: `SetLastTotalPower`, `GetLastTotalPower`
* remove `Keeper`: `SetLastTotalPower`, `GetLastTotalPower`
* [#17335](https://github.com/cosmos/cosmos-sdk/pull/17335) Remove usage of `"cosmossdk.io/x/staking/types".Infraction_*` in favour of `"cosmossdk.io/api/cosmos/staking/v1beta1".Infraction_` in order to remove dependency between modules on staking
* [#17655](https://github.com/cosmos/cosmos-sdk/pull/17655) `QueryHistoricalInfo` was adjusted to return `HistoricalRecord` and marked `Hist` as deprecated.
* [#19414](https://github.com/cosmos/cosmos-sdk/pull/19414) Staking module takes an environment variable in `NewStakingKeeper` instead of individual services.
* [#19754](https://github.com/cosmos/cosmos-sdk/pull/19754) update to use `[]module.ValidatorUpdate` as return for `ApplyAndReturnValidatorSetUpdates`.

### State Breaking changes

* [#18841](https://github.com/cosmos/cosmos-sdk/pull/18841) In a undelegation or redelegation if the shares being left delegated correspond to less than 1 token (in base denom) the entire delegation gets removed.
* [#18142](https://github.com/cosmos/cosmos-sdk/pull/18142) Introduce `key_rotation_fee` param to calculate fees while rotating the keys
* [#17655](https://github.com/cosmos/cosmos-sdk/pull/17655) `HistoricalInfo` was replaced with `HistoricalRecord`, it removes the validator set and comet header and only keep what is needed for IBC.
* [#19740](https://github.com/cosmos/cosmos-sdk/pull/19740) Verify `InitGenesis` and `ExportGenesis` module code and keeper code do not panic.
* [#19740](https://github.com/cosmos/cosmos-sdk/pull/19740) Verify `InitGenesis` and `ExportGenesis` module code and keeper code do not panic.
4 changes: 2 additions & 2 deletions x/staking/keeper/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import (
"context"
"time"

"cosmossdk.io/core/appmodule"
"cosmossdk.io/x/staking/types"

"github.com/cosmos/cosmos-sdk/telemetry"
"github.com/cosmos/cosmos-sdk/types/module"
)

// BeginBlocker will persist the current header and validator set as a historical entry
Expand All @@ -18,7 +18,7 @@ func (k *Keeper) BeginBlocker(ctx context.Context) error {
}

// EndBlocker called at every block, update validator set
func (k *Keeper) EndBlocker(ctx context.Context) ([]module.ValidatorUpdate, error) {
func (k *Keeper) EndBlocker(ctx context.Context) ([]appmodule.ValidatorUpdate, error) {
defer telemetry.ModuleMeasureSince(types.ModuleName, time.Now(), telemetry.MetricKeyEndBlocker)
return k.BlockValidatorUpdates(ctx)
}
6 changes: 3 additions & 3 deletions x/staking/keeper/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,19 @@ import (
"fmt"

"cosmossdk.io/collections"
"cosmossdk.io/core/appmodule"
"cosmossdk.io/math"
"cosmossdk.io/x/staking/types"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
)

// InitGenesis sets the pool and parameters for the provided keeper. For each
// validator in data, it sets that validator in the keeper along with manually
// setting the indexes. In addition, it also sets any delegations found in
// data. Finally, it updates the bonded validators.
// Returns final validator set after applying all declaration and delegations
func (k Keeper) InitGenesis(ctx context.Context, data *types.GenesisState) ([]module.ValidatorUpdate, error) {
func (k Keeper) InitGenesis(ctx context.Context, data *types.GenesisState) ([]appmodule.ValidatorUpdate, error) {
bondedTokens := math.ZeroInt()
notBondedTokens := math.ZeroInt()

Expand Down Expand Up @@ -175,7 +175,7 @@ func (k Keeper) InitGenesis(ctx context.Context, data *types.GenesisState) ([]mo
}

// don't need to run CometBFT updates if we exported
var moduleValidatorUpdates []module.ValidatorUpdate
var moduleValidatorUpdates []appmodule.ValidatorUpdate
if data.Exported {
for _, lv := range data.LastValidatorPowers {
valAddr, err := k.validatorAddressCodec.StringToBytes(lv.Address)
Expand Down
48 changes: 46 additions & 2 deletions x/staking/keeper/keeper.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package keeper

import (
"encoding/json"
"fmt"
"time"

Expand Down Expand Up @@ -41,6 +42,49 @@ func HistoricalInfoCodec(cdc codec.BinaryCodec) collcodec.ValueCodec[types.Histo
})
}

type moduleValidatorUpdatesCodec struct {
cdc codec.BinaryCodec
}

// Decode implements codec.ValueCodec.
func (m moduleValidatorUpdatesCodec) Decode(b []byte) (types.ModuleValidatorUpdates, error) {
var mvu types.ModuleValidatorUpdates
if err := json.Unmarshal(b, &mvu); err != nil {
return types.ModuleValidatorUpdates{}, err
}

return mvu, nil
}

// DecodeJSON implements codec.ValueCodec.
func (m moduleValidatorUpdatesCodec) DecodeJSON(b []byte) (types.ModuleValidatorUpdates, error) {
return m.Decode(b)
}

// Encode implements codec.ValueCodec.
func (m moduleValidatorUpdatesCodec) Encode(value types.ModuleValidatorUpdates) ([]byte, error) {
return json.Marshal(value)
}

// EncodeJSON implements codec.ValueCodec.
func (m moduleValidatorUpdatesCodec) EncodeJSON(value types.ModuleValidatorUpdates) ([]byte, error) {
return m.Encode(value)
}

// Stringify implements codec.ValueCodec.
func (m moduleValidatorUpdatesCodec) Stringify(value types.ModuleValidatorUpdates) string {
return fmt.Sprintf("%v", value)
}

// ValueType implements codec.ValueCodec.
func (m moduleValidatorUpdatesCodec) ValueType() string {
return "types.ModuleValidatorUpdates"
}

func ValidatorUpdateCodec(cdc codec.BinaryCodec) collcodec.ValueCodec[types.ModuleValidatorUpdates] {
return moduleValidatorUpdatesCodec{cdc}
}

type rotationHistoryIndexes struct {
Block *indexes.Multi[uint64, collections.Pair[[]byte, uint64], types.ConsPubKeyRotationHistory]
}
Expand Down Expand Up @@ -84,7 +128,7 @@ type Keeper struct {
// LastTotalPower value: LastTotalPower
LastTotalPower collections.Item[math.Int]
// ValidatorUpdates value: ValidatorUpdates
ValidatorUpdates collections.Item[types.ValidatorUpdates]
ValidatorUpdates collections.Item[types.ModuleValidatorUpdates]
// DelegationsByValidator key: valAddr+delAddr | value: none used (index key for delegations by validator index)
DelegationsByValidator collections.Map[collections.Pair[sdk.ValAddress, sdk.AccAddress], []byte]
UnbondingID collections.Sequence
Expand Down Expand Up @@ -171,7 +215,7 @@ func NewKeeper(
consensusAddressCodec: consensusAddressCodec,
LastTotalPower: collections.NewItem(sb, types.LastTotalPowerKey, "last_total_power", sdk.IntValue),
HistoricalInfo: collections.NewMap(sb, types.HistoricalInfoKey, "historical_info", collections.Uint64Key, HistoricalInfoCodec(cdc)),
ValidatorUpdates: collections.NewItem(sb, types.ValidatorUpdatesKey, "validator_updates", codec.CollValue[types.ValidatorUpdates](cdc)),
ValidatorUpdates: collections.NewItem(sb, types.ValidatorUpdatesKey, "validator_updates", ValidatorUpdateCodec(cdc)),
Delegations: collections.NewMap(
sb, types.DelegationKey, "delegations",
collections.PairKeyCodec(
Expand Down
44 changes: 10 additions & 34 deletions x/staking/keeper/val_state_change.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,23 @@ import (
"fmt"
"sort"

abci "github.com/cometbft/cometbft/abci/types"
gogotypes "github.com/cosmos/gogoproto/types"

"cosmossdk.io/core/address"
"cosmossdk.io/core/appmodule"
"cosmossdk.io/core/event"
errorsmod "cosmossdk.io/errors"
"cosmossdk.io/math"
"cosmossdk.io/x/staking/types"

cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/types/module"
)

// BlockValidatorUpdates calculates the ValidatorUpdates for the current block
// Called in each EndBlock
func (k Keeper) BlockValidatorUpdates(ctx context.Context) ([]module.ValidatorUpdate, error) {
func (k Keeper) BlockValidatorUpdates(ctx context.Context) ([]appmodule.ValidatorUpdate, error) {
// Calculate validator set changes.
//
// NOTE: ApplyAndReturnValidatorSetUpdates has to come before
Expand Down Expand Up @@ -138,7 +136,7 @@ func (k Keeper) BlockValidatorUpdates(ctx context.Context) ([]module.ValidatorUp
// CONTRACT: Only validators with non-zero power or zero-power that were bonded
// at the previous block height or were removed from the validator set entirely
// are returned to CometBFT.
func (k Keeper) ApplyAndReturnValidatorSetUpdates(ctx context.Context) ([]module.ValidatorUpdate, error) {
func (k Keeper) ApplyAndReturnValidatorSetUpdates(ctx context.Context) ([]appmodule.ValidatorUpdate, error) {
params, err := k.Params.Get(ctx)
if err != nil {
return nil, err
Expand All @@ -163,8 +161,7 @@ func (k Keeper) ApplyAndReturnValidatorSetUpdates(ctx context.Context) ([]module
}
defer iterator.Close()

var updates []abci.ValidatorUpdate
var moduleValidatorUpdates []module.ValidatorUpdate
var updates []appmodule.ValidatorUpdate
for count := 0; iterator.Valid() && count < int(maxValidators); iterator.Next() {
// everything that is iterated in this loop is becoming or already a
// part of the bonded validator set
Expand Down Expand Up @@ -215,8 +212,7 @@ func (k Keeper) ApplyAndReturnValidatorSetUpdates(ctx context.Context) ([]module

// update the validator set if power has changed
if !found || !bytes.Equal(oldPowerBytes, newPowerBytes) {
updates = append(updates, validator.ABCIValidatorUpdate(powerReduction))
moduleValidatorUpdates = append(moduleValidatorUpdates, validator.ModuleValidatorUpdate(powerReduction))
updates = append(updates, validator.ModuleValidatorUpdate(powerReduction))
if err = k.SetLastValidatorPower(ctx, valAddr, newPower); err != nil {
return nil, err
}
Expand Down Expand Up @@ -251,8 +247,7 @@ func (k Keeper) ApplyAndReturnValidatorSetUpdates(ctx context.Context) ([]module
return nil, err
}

updates = append(updates, validator.ABCIValidatorUpdateZero())
moduleValidatorUpdates = append(moduleValidatorUpdates, validator.ModuleValidatorUpdateZero())
updates = append(updates, validator.ModuleValidatorUpdateZero())
}

// ApplyAndReturnValidatorSetUpdates checks if there is ConsPubKeyRotationHistory
Expand All @@ -278,41 +273,23 @@ func (k Keeper) ApplyAndReturnValidatorSetUpdates(ctx context.Context) ([]module
if !ok {
return nil, errorsmod.Wrapf(sdkerrors.ErrInvalidType, "Expecting cryptotypes.PubKey, got %T", oldPk)
}
oldCmtPk, err := cryptocodec.ToCmtProtoPublicKey(oldPk)
if err != nil {
return nil, err
}

newPk, ok := history.NewConsPubkey.GetCachedValue().(cryptotypes.PubKey)
if !ok {
return nil, errorsmod.Wrapf(sdkerrors.ErrInvalidType, "Expecting cryptotypes.PubKey, got %T", newPk)
}
newCmtPk, err := cryptocodec.ToCmtProtoPublicKey(newPk)
if err != nil {
return nil, err
}

// a validator cannot rotate keys if it's not bonded or if it's jailed
// - a validator can be unbonding state but jailed status false
// - a validator can be jailed and status can be unbonding
if !(validator.Jailed || validator.Status != types.Bonded) {
updates = append(updates, abci.ValidatorUpdate{
PubKey: oldCmtPk,
Power: 0,
})

moduleValidatorUpdates = append(moduleValidatorUpdates, module.ValidatorUpdate{
updates = append(updates, appmodule.ValidatorUpdate{
PubKey: oldPk.Bytes(),
PubKeyType: oldPk.Type(),
Power: 0,
})

updates = append(updates, abci.ValidatorUpdate{
PubKey: newCmtPk,
Power: validator.ConsensusPower(powerReduction),
})

moduleValidatorUpdates = append(moduleValidatorUpdates, module.ValidatorUpdate{
updates = append(updates, appmodule.ValidatorUpdate{
PubKey: newPk.Bytes(),
PubKeyType: newPk.Type(),
Power: validator.ConsensusPower(powerReduction),
Expand Down Expand Up @@ -350,13 +327,12 @@ func (k Keeper) ApplyAndReturnValidatorSetUpdates(ctx context.Context) ([]module
}
}

valUpdates := types.ValidatorUpdates{Updates: updates}
// set the list of validator updates
if err = k.ValidatorUpdates.Set(ctx, valUpdates); err != nil {
if err = k.ValidatorUpdates.Set(ctx, updates); err != nil {
return nil, err
}

return moduleValidatorUpdates, err
return updates, err
}

// Validator state transitions
Expand Down
4 changes: 2 additions & 2 deletions x/staking/keeper/validator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"github.com/golang/mock/gomock"

"cosmossdk.io/collections"
"cosmossdk.io/core/appmodule"
"cosmossdk.io/core/header"
"cosmossdk.io/math"
authtypes "cosmossdk.io/x/auth/types"
Expand All @@ -14,10 +15,9 @@ import (
stakingtypes "cosmossdk.io/x/staking/types"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
)

func (s *KeeperTestSuite) applyValidatorSetUpdates(ctx sdk.Context, keeper *stakingkeeper.Keeper, expectedUpdatesLen int) []module.ValidatorUpdate {
func (s *KeeperTestSuite) applyValidatorSetUpdates(ctx sdk.Context, keeper *stakingkeeper.Keeper, expectedUpdatesLen int) []appmodule.ValidatorUpdate {
updates, err := keeper.ApplyAndReturnValidatorSetUpdates(ctx)
s.Require().NoError(err)
if expectedUpdatesLen >= 0 {
Expand Down
Loading

0 comments on commit 100f280

Please sign in to comment.