Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ValSet-Pref] Module Wired up and created MsgSetValidatorSetPreference #2892

Merged
merged 3 commits into from
Nov 6, 2022
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Module Wired up and created MsgSetValidatorSetPreference
stackman27 committed Nov 4, 2022
commit 4294b9256b83d83a85376a61064900da47b2b128
13 changes: 13 additions & 0 deletions app/keepers/keepers.go
Original file line number Diff line number Diff line change
@@ -75,6 +75,8 @@ import (
"github.com/osmosis-labs/osmosis/v12/x/txfees"
txfeeskeeper "github.com/osmosis-labs/osmosis/v12/x/txfees/keeper"
txfeestypes "github.com/osmosis-labs/osmosis/v12/x/txfees/types"
validatorpreference "github.com/osmosis-labs/osmosis/v12/x/validator-preference"
validatorpreferencetypes "github.com/osmosis-labs/osmosis/v12/x/validator-preference/types"
)

type AppKeepers struct {
@@ -338,6 +340,16 @@ func (appKeepers *AppKeepers) InitNormalKeepers(
)
appKeepers.TokenFactoryKeeper = &tokenFactoryKeeper

validatorPreferenceKeeper := validatorpreference.NewKeeper(
appKeepers.keys[validatorpreferencetypes.StoreKey],
appKeepers.GetSubspace(validatorpreferencetypes.ModuleName),
appKeepers.StakingKeeper,
appKeepers.BankKeeper,
appKeepers.DistrKeeper,
)

appKeepers.ValidatorPreferenceKeeper = &validatorPreferenceKeeper
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is a reference to the keeper needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that was a part of wiring up the keeper

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but why is a reference necessary? Typically keepers are non-mutative -- there are a few exceptions like staking where we need to set hooks after the fact.


// The last arguments can contain custom message handlers, and custom query handlers,
// if we want to allow any custom callbacks
supportedFeatures := "iterator,staking,stargate,osmosis"
@@ -556,5 +568,6 @@ func KVStoreKeys() []string {
superfluidtypes.StoreKey,
wasm.StoreKey,
tokenfactorytypes.StoreKey,
validatorpreferencetypes.StoreKey,
}
}
16 changes: 16 additions & 0 deletions osmoutils/slice_helper.go
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@ import (
"sort"

"golang.org/x/exp/constraints"

)

// SortSlice sorts a slice of type T elements that implement constraints.Ordered.
@@ -35,3 +36,18 @@ func ReverseSlice[T any](s []T) []T {
}
return s
}

// ContainsDuplicate checks if there are any duplicate
// elements in the slice.
func ContainsDuplicate[T any](arr []T) bool {
visited := make(map[any]bool, 0)
for i := 0; i < len(arr); i++ {
if visited[arr[i]] {
return true
} else {
visited[arr[i]] = true
}
}
return false
}

15 changes: 15 additions & 0 deletions proto/osmosis/validator-preference/v1beta1/genesis.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
syntax = "proto3";
package osmosis.validatorpreference.v1beta1;

import "gogoproto/gogo.proto";
import "google/api/annotations.proto";
import "osmosis/validator-preference/v1beta1/params.proto";

option go_package = "github.com/osmosis-labs/osmosis/v12/x/validator-preference/types";
option (gogoproto.goproto_getters_all) = false;

// GenesisState defines the validator-set preference module's genesis state.
message GenesisState {
// params defines the paramaters of the module.
Params params = 1 [ (gogoproto.nullable) = false ];
}
17 changes: 17 additions & 0 deletions proto/osmosis/validator-preference/v1beta1/params.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
syntax = "proto3";
package osmosis.validatorpreference.v1beta1;

import "gogoproto/gogo.proto";
import "cosmos_proto/cosmos.proto";
import "cosmos/base/v1beta1/coin.proto";

option go_package = "github.com/osmosis-labs/osmosis/v12/x/validator-preference/types";

// Params defines the parameters for the module.
message Params {
repeated cosmos.base.v1beta1.Coin valset_creation_fee = 1 [
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins",
(gogoproto.moretags) = "yaml:\"valset_creation_fee\"",
(gogoproto.nullable) = false
];
}
20 changes: 20 additions & 0 deletions x/validator-preference/genesis.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package keeper

import (
"github.com/osmosis-labs/osmosis/v12/x/validator-preference/types"

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

// InitGenesis initializes the capability module's state from a provided genesis
// state.
func (k Keeper) InitGenesis(ctx sdk.Context, genState types.GenesisState) {
k.SetParams(ctx, genState.Params)
}

// ExportGenesis returns the capability module's exported genesis.
func (k Keeper) ExportGenesis(ctx sdk.Context) *types.GenesisState {
return &types.GenesisState{
Params: k.GetParams(ctx),
}
}
77 changes: 77 additions & 0 deletions x/validator-preference/keeper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package keeper

import (
"fmt"

"github.com/tendermint/tendermint/libs/log"

sdk "github.com/cosmos/cosmos-sdk/types"
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
"github.com/gogo/protobuf/proto"
"github.com/osmosis-labs/osmosis/v12/osmoutils"
"github.com/osmosis-labs/osmosis/v12/x/validator-preference/types"
)

type Keeper struct {
storeKey sdk.StoreKey
paramSpace paramtypes.Subspace
stakingKeeper types.StakingInterface
bankKeeper types.BankInterface
distrKeeper types.DistrInterface
}

func NewKeeper(storeKey sdk.StoreKey,
paramSpace paramtypes.Subspace,
stakingKeeper types.StakingInterface,
bankKeeper types.BankInterface,
distrKeeper types.DistrInterface,
) Keeper {
if !paramSpace.HasKeyTable() {
paramSpace = paramSpace.WithKeyTable(types.ParamKeyTable())
}

return Keeper{
storeKey: storeKey,
paramSpace: paramSpace,
stakingKeeper: stakingKeeper,
bankKeeper: bankKeeper,
distrKeeper: distrKeeper,
}
}

func (k Keeper) Logger(ctx sdk.Context) log.Logger {
return ctx.Logger().With("module", fmt.Sprintf("x/%s", types.ModuleName))
}

func (k Keeper) SetValidatorSetPreferences(ctx sdk.Context, delegator string, validators types.ValidatorSetPreferences) {
store := ctx.KVStore(k.storeKey)
osmoutils.MustSet(store, []byte(delegator), &validators)
}

func (k Keeper) GetValidatorSetPreference(ctx sdk.Context, delegator string) (types.ValidatorSetPreferences, bool) {
validatorSet := types.ValidatorSetPreferences{}

store := ctx.KVStore(k.storeKey)
b := store.Get([]byte(delegator))
if b == nil {
return types.ValidatorSetPreferences{}, false
}

err := proto.Unmarshal(b, &validatorSet)
if err != nil {
return types.ValidatorSetPreferences{}, false
}

return validatorSet, true
}

// GetParams returns the total set params.
func (k Keeper) GetParams(ctx sdk.Context) (params types.Params) {
k.paramSpace.GetParamSet(ctx, &params)
return params
}

// SetParams sets the total set of params.
func (k Keeper) SetParams(ctx sdk.Context, params types.Params) {
k.paramSpace.SetParamSet(ctx, &params)
}
52 changes: 52 additions & 0 deletions x/validator-preference/keeper_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package keeper_test

import (
"testing"

sdk "github.com/cosmos/cosmos-sdk/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
"github.com/osmosis-labs/osmosis/v12/app/apptesting"
"github.com/osmosis-labs/osmosis/v12/x/validator-preference/types"
"github.com/stretchr/testify/suite"
)

type KeeperTestSuite struct {
apptesting.KeeperTestHelper
}

func (suite *KeeperTestSuite) SetupTest() {
suite.Setup()
}

// SetupMultipleValidators setups "numValidator" validators and returns their address in string
func (suite *KeeperTestSuite) SetupMultipleValidators(numValidator int) []string {
valAddrs := []string{}
for i := 0; i < numValidator; i++ {
valAddr := suite.SetupValidator(stakingtypes.Bonded)
valAddrs = append(valAddrs, valAddr.String())
}
return valAddrs
}

func (suite *KeeperTestSuite) PrepareDelegateToValidatorSet() []types.ValidatorPreference {
valAddrs := suite.SetupMultipleValidators(3)
valPreferences := []types.ValidatorPreference{
{
ValOperAddress: valAddrs[0],
Weight: sdk.NewDecWithPrec(5, 1),
},
{
ValOperAddress: valAddrs[1],
Weight: sdk.NewDecWithPrec(3, 1),
},
{
ValOperAddress: valAddrs[2],
Weight: sdk.NewDecWithPrec(2, 1),
},
}
return valPreferences
}

func TestKeeperTestSuite(t *testing.T) {
suite.Run(t, new(KeeperTestSuite))
}
72 changes: 72 additions & 0 deletions x/validator-preference/msg_server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package keeper

import (
"context"
"fmt"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/osmosis-labs/osmosis/v12/x/validator-preference/types"
)

type msgServer struct {
keeper *Keeper
}

// NewMsgServerImpl returns an implementation of the MsgServer interface
// for the provided Keeper.
func NewMsgServerImpl(keeper *Keeper) types.MsgServer {
return &msgServer{
keeper: keeper,
}
}

var _ types.MsgServer = msgServer{}

func (server msgServer) SetValidatorSetPreference(goCtx context.Context, msg *types.MsgSetValidatorSetPreference) (*types.MsgSetValidatorSetPreferenceResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)

// new user preference
preferences := msg.Preferences

// check if a user already has a validator-set created
existingValidators, found := server.keeper.GetValidatorSetPreference(ctx, msg.Delegator)
if found {
// check if the new preferences is the same as the existing preferences
isEqual := server.keeper.SortAndCompareValidatorSet(preferences, existingValidators.Preferences)
if isEqual {
return nil, fmt.Errorf("The preferences (validator and weights) are the same")
}
}

// checks that all the validators exist on chain
err := server.keeper.ValidatePreferences(ctx, preferences)
if err != nil {
return nil, err
}

// charge fee to execute this message
err = server.keeper.ChargeForCreateValSet(ctx, msg.Delegator)
if err != nil {
return nil, err
}

// create/update the validator-set based on what user provides
setMsg := types.ValidatorSetPreferences{
Preferences: msg.Preferences,
}

server.keeper.SetValidatorSetPreferences(ctx, msg.Delegator, setMsg)
return &types.MsgSetValidatorSetPreferenceResponse{}, nil
}

func (server msgServer) DelegateToValidatorSet(goCtx context.Context, msg *types.MsgDelegateToValidatorSet) (*types.MsgDelegateToValidatorSetResponse, error) {
return &types.MsgDelegateToValidatorSetResponse{}, nil
}

func (server msgServer) UndelegateFromValidatorSet(goCtx context.Context, msg *types.MsgUndelegateFromValidatorSet) (*types.MsgUndelegateFromValidatorSetResponse, error) {
return &types.MsgUndelegateFromValidatorSetResponse{}, nil
}

func (server msgServer) WithdrawDelegationRewards(goCtx context.Context, msg *types.MsgWithdrawDelegationRewards) (*types.MsgWithdrawDelegationRewardsResponse, error) {
return &types.MsgWithdrawDelegationRewardsResponse{}, nil
}
Loading