Skip to content

Commit

Permalink
feat: add pool/operator/service params
Browse files Browse the repository at this point in the history
  • Loading branch information
hallazzang committed Jul 30, 2024
1 parent dae139e commit f72ddb9
Show file tree
Hide file tree
Showing 43 changed files with 4,874 additions and 373 deletions.
7 changes: 5 additions & 2 deletions proto/milkyway/pools/v1/genesis.proto
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,22 @@ package milkyway.pools.v1;
import "gogoproto/gogo.proto";
import "google/protobuf/timestamp.proto";
import "milkyway/pools/v1/models.proto";
import "milkyway/pools/v1/params.proto";

option go_package = "github.com/milkyway-labs/milkyway/x/pools/types";

// GenesisState defines the pools module's genesis state.
message GenesisState {
// Params defines the parameters of the module.
Params params = 1 [ (gogoproto.nullable) = false ];

// NextPoolID represents the id to be used when creating the next pool.
uint32 next_pool_id = 1 [
uint32 next_pool_id = 2 [
(gogoproto.customname) = "NextPoolID",
(gogoproto.moretags) = "yaml:\"next_pool_id\""
];

// Operators defines the list of pools.
repeated Pool pools = 2
repeated Pool pools = 3
[ (gogoproto.moretags) = "yaml:\"pools\"", (gogoproto.nullable) = false ];
}
16 changes: 16 additions & 0 deletions proto/milkyway/pools/v1/params.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
syntax = "proto3";
package milkyway.pools.v1;

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

option go_package = "github.com/milkyway-labs/milkyway/x/pools/types";

// Params defines the parameters for the pools module.
message Params {
// AllowedServiceIDs defines the list of service IDs that the module allows
// to join by pools.
repeated uint32 allowed_service_ids = 1
[ (gogoproto.customname) = "AllowedServiceIDs" ];
}
20 changes: 19 additions & 1 deletion proto/milkyway/restaking/v1/genesis.proto
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,29 @@ import "milkyway/restaking/v1/params.proto";

option go_package = "github.com/milkyway-labs/milkyway/x/restaking/types";

message OperatorParamsRecord {
uint32 operator_id = 1 [ (gogoproto.customname) = "OperatorID" ];

OperatorParams params = 2 [ (gogoproto.nullable) = false ];
}

message ServiceParamsRecord {
uint32 service_id = 1 [ (gogoproto.customname) = "ServiceID" ];

ServiceParams params = 2 [ (gogoproto.nullable) = false ];
}

// GenesisState defines the restaking module's genesis state.
message GenesisState {
// Params defines the parameters of the module.
Params params = 1 [ (gogoproto.nullable) = false ];

repeated OperatorParamsRecord operator_params = 2
[ (gogoproto.nullable) = false ];

repeated ServiceParamsRecord service_params = 3
[ (gogoproto.nullable) = false ];

// Delegations represents the delegations.
repeated Delegation delegations = 2 [ (gogoproto.nullable) = false ];
repeated Delegation delegations = 4 [ (gogoproto.nullable) = false ];
}
34 changes: 34 additions & 0 deletions proto/milkyway/restaking/v1/messages.proto
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,22 @@ import "cosmos/bank/v1beta1/bank.proto";
import "cosmos/msg/v1/msg.proto";
import "gogoproto/gogo.proto";
import "milkyway/restaking/v1/params.proto";
import "milkyway/restaking/v1/models.proto";

option go_package = "github.com/milkyway-labs/milkyway/x/restaking/types";

// Msg defines the restaking module's gRPC message service.
service Msg {
option (cosmos.msg.v1.service) = true;

// UpdateOperatorParams defines the operation for joining a service as an
// operator.
rpc UpdateOperatorParams(MsgUpdateOperatorParams)
returns (MsgUpdateOperatorParamsResponse);

rpc UpdateServiceParams(MsgUpdateServiceParams)
returns (MsgUpdateServiceParamsResponse);

// DelegatePool defines the operation that allows users to delegate any amount
// of an asset to a pool that can then be used to provide services with
// cryptoeconomic security.
Expand All @@ -35,6 +44,31 @@ service Msg {
rpc UpdateParams(MsgUpdateParams) returns (MsgUpdateParamsResponse);
}

// MsgUpdateOperatorParams defines the message structure for the
// UpdateOperatorParams gRPC service method. It allows the operator admin to
// update the operator's parameters.
message MsgUpdateOperatorParams {
string sender = 1 [ (cosmos_proto.scalar) = "cosmos.AddressString" ];

uint32 operator_id = 2 [ (gogoproto.customname) = "OperatorID" ];

OperatorParams operator_params = 3 [ (gogoproto.nullable) = false ];
}

// MsgUpdateOperatorParamsResponse is the return value of
// MsgUpdateOperatorParams.
message MsgUpdateOperatorParamsResponse {}

message MsgUpdateServiceParams {
string sender = 1 [ (cosmos_proto.scalar) = "cosmos.AddressString" ];

uint32 service_id = 2 [ (gogoproto.customname) = "ServiceID" ];

ServiceParams service_params = 3 [ (gogoproto.nullable) = false ];
}

message MsgUpdateServiceParamsResponse {}

// MsgDelegatePool defines the message structure for the DelegatePool gRPC
// service method. It allows a user to put their assets into a restaking pool
// that will later be used to provide cryptoeconomic security to services that
Expand Down
25 changes: 25 additions & 0 deletions proto/milkyway/restaking/v1/models.proto
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,31 @@ import "cosmos/base/v1beta1/coin.proto";

option go_package = "github.com/milkyway-labs/milkyway/x/restaking/types";

message OperatorParams {
// CommissionRate defines the commission rate charged to delegators, as a
// fraction.
string commission_rate = 1 [
(gogoproto.customtype) = "cosmossdk.io/math.LegacyDec",
(gogoproto.nullable) = false
];

repeated uint32 joined_service_ids = 2
[ (gogoproto.customname) = "JoinedServiceIDs" ];
}

message ServiceParams {
string slash_fraction = 1 [
(gogoproto.customtype) = "cosmossdk.io/math.LegacyDec",
(gogoproto.nullable) = false
];

repeated uint32 whitelisted_pool_ids = 2
[ (gogoproto.customname) = "WhitelistedPoolIDs" ];

repeated uint32 whitelisted_operator_ids = 3
[ (gogoproto.customname) = "WhitelistedOperatorIDs" ];
}

// DelegationType defines the type of delegation.
enum DelegationType {
option (gogoproto.goproto_enum_prefix) = false;
Expand Down
39 changes: 39 additions & 0 deletions proto/milkyway/restaking/v1/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,19 @@ option go_package = "github.com/milkyway-labs/milkyway/x/restaking/types";

// Query defines the gRPC querier service.
service Query {
rpc OperatorParams(QueryOperatorParamsRequest)
returns (QueryOperatorParamsResponse) {
option (cosmos.query.v1.module_query_safe) = true;
option (google.api.http).get =
"/milkyway/restaking/v1/operator_params/{operator_id}";
}

rpc ServiceParams(QueryServiceParamsRequest)
returns (QueryServiceParamsResponse) {
option (cosmos.query.v1.module_query_safe) = true;
option (google.api.http).get =
"/milkyway/restaking/v1/service_params/{service_id}";
}

// PoolDelegations queries the delegations info for the given pool.
rpc PoolDelegations(QueryPoolDelegationsRequest)
Expand Down Expand Up @@ -157,6 +170,32 @@ service Query {
}
}

// QueryOperatorParamsRequest is request type for the Query/OperatorParams
// RPC method.
message QueryOperatorParamsRequest {
// OperatorId is the ID of the operator to query
uint32 operator_id = 1;
}

// QueryOperatorParamsResponse is response type for the Query/OperatorParams
// RPC method.
message QueryOperatorParamsResponse {
OperatorParams operator_params = 1 [ (gogoproto.nullable) = false ];
}

// QueryServiceParamsRequest is request type for the Query/ServiceParams
// RPC method.
message QueryServiceParamsRequest {
// ServiceId is the ID of the service to query
uint32 service_id = 1;
}

// QueryServiceParamsResponse is response type for the Query/ServiceParams
// RPC method.
message QueryServiceParamsResponse {
ServiceParams service_params = 1 [ (gogoproto.nullable) = false ];
}

// QueryPoolDelegationsRequest is request type for the Query/PoolDelegations RPC
// method.
message QueryPoolDelegationsRequest {
Expand Down
26 changes: 26 additions & 0 deletions utils/key.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package utils

import (
"bytes"
"encoding/binary"
)

func CompositeKey(parts ...[]byte) []byte {
return bytes.Join(parts, nil)
}

// Uint32ToBigEndian marshals uint32 to a bigendian byte slice so it can be sorted
func Uint32ToBigEndian(i uint32) []byte {
b := make([]byte, 4)
binary.BigEndian.PutUint32(b, i)
return b
}

// BigEndianToUint32 returns an uint32 from big endian encoded bytes. If encoding
// is empty, zero is returned.
func BigEndianToUint32(bz []byte) uint32 {
if len(bz) == 0 {
return 0
}
return binary.BigEndian.Uint32(bz)
}
10 changes: 9 additions & 1 deletion utils/slices.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,15 @@ package utils

// FindDuplicate returns the first duplicate element in the slice.
// If no duplicates are found, it returns nil instead.
func FindDuplicate[T any](slice []T, compare func(a T, b T) bool) *T {
func FindDuplicate[T comparable](slice []T) *T {
return FindDuplicateFunc(slice, func(a, b T) bool {
return a == b
})
}

// FindDuplicateFunc returns the first duplicate element in the slice.
// If no duplicates are found, it returns nil instead.
func FindDuplicateFunc[T any](slice []T, compare func(a T, b T) bool) *T {
for i, a := range slice {
for j, b := range slice {
if i != j && compare(a, b) {
Expand Down
21 changes: 21 additions & 0 deletions utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -307,3 +307,24 @@ func VerifyTxHash(txHash string) (err error) {
}
return nil
}

func ParseUint32Slice(s string) ([]uint32, error) {
ss := strings.Split(s, ",")
out := make([]uint32, len(ss))
for i, d := range ss {
u, err := strconv.ParseUint(d, 10, 32)
if err != nil {
return nil, err
}
out[i] = uint32(u)
}
return out, nil
}

func FormatUint32Slice(s []uint32) string {
ss := make([]string, len(s))
for i, u := range s {
ss[i] = fmt.Sprint(u)
}
return strings.Join(ss, ",")
}
4 changes: 2 additions & 2 deletions x/operators/types/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,15 +70,15 @@ func (data *GenesisState) Validate() error {
// findDuplicateOperators returns the first duplicated operator in the slice.
// If no duplicates are found, it returns nil instead.
func findDuplicateOperators(operators []Operator) *Operator {
return utils.FindDuplicate(operators, func(a, b Operator) bool {
return utils.FindDuplicateFunc(operators, func(a, b Operator) bool {
return a.ID == b.ID
})
}

// findDuplicateUnbondingOperators returns the first duplicated unbonding operator in the slice.
// If no duplicates are found, it returns nil instead.
func findDuplicateUnbondingOperators(operators []UnbondingOperator) *UnbondingOperator {
return utils.FindDuplicate(operators, func(a, b UnbondingOperator) bool {
return utils.FindDuplicateFunc(operators, func(a, b UnbondingOperator) bool {
return a.OperatorID == b.OperatorID
})
}
Expand Down
2 changes: 1 addition & 1 deletion x/operators/types/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func GetOperatorIDFromBytes(bz []byte) (operatorID uint32) {
return binary.BigEndian.Uint32(bz)
}

// OperatorStoreKey turns a operator ID into a key used to store a operator in the KVStore
// OperatorStoreKey returns a operator ID into a key used to store a operator in the KVStore
func OperatorStoreKey(operatorID uint32) []byte {
return append(OperatorPrefix, GetOperatorIDBytes(operatorID)...)
}
Expand Down
3 changes: 3 additions & 0 deletions x/pools/keeper/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
// ExportGenesis returns a new GenesisState instance containing the information currently present inside the store
func (k *Keeper) ExportGenesis(ctx sdk.Context) *types.GenesisState {
return types.NewGenesis(
k.GetParams(ctx),
k.exportNextPoolID(ctx),
k.GetPools(ctx),
)
Expand All @@ -27,6 +28,8 @@ func (k *Keeper) exportNextPoolID(ctx sdk.Context) uint32 {

// InitGenesis initializes the genesis store using the provided data
func (k *Keeper) InitGenesis(ctx sdk.Context, data *types.GenesisState) {
k.SetParams(ctx, data.Params)

// Set the next pool id
k.SetNextPoolID(ctx, data.NextPoolID)

Expand Down
1 change: 1 addition & 0 deletions x/pools/keeper/genesis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ func (suite *KeeperTestSuite) TestKeeper_InitGenesis() {
{
name: "genesis with pools is initialized properly",
genesis: types.NewGenesis(
types.DefaultParams(),
10,
[]types.Pool{
types.NewPool(1, "umilk"),
Expand Down
25 changes: 25 additions & 0 deletions x/pools/keeper/params.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package keeper

import (
sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/milkyway-labs/milkyway/x/pools/types"
)

// SetParams sets module parameters
func (k *Keeper) SetParams(ctx sdk.Context, params types.Params) {
store := ctx.KVStore(k.storeKey)
bz := k.cdc.MustMarshal(&params)
store.Set(types.ParamsKey, bz)
}

// GetParams returns the module parameters
func (k *Keeper) GetParams(ctx sdk.Context) (p types.Params) {
store := ctx.KVStore(k.storeKey)
bz := store.Get(types.ParamsKey)
if bz == nil {
return p
}
k.cdc.MustUnmarshal(bz, &p)
return p
}
12 changes: 9 additions & 3 deletions x/pools/types/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,34 @@ import (
)

// NewGenesis creates a new GenesisState instance
func NewGenesis(nextPoolID uint32, pools []Pool) *GenesisState {
func NewGenesis(params Params, nextPoolID uint32, pools []Pool) *GenesisState {
return &GenesisState{
Params: params,
NextPoolID: nextPoolID,
Pools: pools,
}
}

// DefaultGenesis returns the default GenesisState
func DefaultGenesis() *GenesisState {
return NewGenesis(1, nil)
return NewGenesis(DefaultParams(), 1, nil)
}

// Validate checks if the GenesisState is valid
func (data *GenesisState) Validate() error {
err := data.Params.Validate()
if err != nil {
return fmt.Errorf("invalid params: %w", err)
}

// Validate the next pool ID
if data.NextPoolID == 0 {
return fmt.Errorf("invalid next pool id")
}

// Validate the pools
for _, pool := range data.Pools {
err := pool.Validate()
err = pool.Validate()
if err != nil {
return fmt.Errorf("invalid pool with id %d: %w", pool.ID, err)
}
Expand Down
Loading

0 comments on commit f72ddb9

Please sign in to comment.