Skip to content

Commit

Permalink
refactor: use a single delegation type (#57)
Browse files Browse the repository at this point in the history
## Description

While starting to implement unbonding, I realized that @hallazzang
suggestion of using a single `Delegation` object was the best thing to
do in order to avoid having code that is copy/pasted just because of
different field names.

This PR refactors the code to use a single `Delegation` type to
represent delegations. Various delegations are distinguished between one
another because of their `type`.

<!-- Add a description of the changes that this PR introduces and the
files that
are the most critical to review. -->

---

### Author Checklist

*All items are required. Please add a note to the item if the item is
not applicable and
please add links to any relevant follow up issues.*

I have...

- [x] included the correct [type
prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json)
in the PR title
- [ ] added `!` to the type prefix if API or client breaking change
- [x] targeted the correct branch (see [PR
Targeting](https://github.com/desmos-labs/desmos/blob/master/CONTRIBUTING.md#pr-targeting))
- [ ] provided a link to the relevant issue or specification
- [x] followed the guidelines for [building
modules](https://docs.cosmos.network/v0.44/building-modules/intro.html)
- [x] included the necessary unit and integration
[tests](https://github.com/desmos-labs/desmos/blob/master/CONTRIBUTING.md#testing)
- [ ] added a changelog entry to `CHANGELOG.md`
- [x] included comments for [documenting Go
code](https://blog.golang.org/godoc)
- [ ] updated the relevant documentation or specification
- [x] reviewed "Files changed" and left comments if necessary
- [x] confirmed all CI checks have passed

### Reviewers Checklist

*All items are required. Please add a note if the item is not applicable
and please add
your handle next to the items reviewed if you only reviewed selected
items.*

I have...

- [ ] confirmed the correct [type
prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json)
in the PR title
- [ ] confirmed `!` in the type prefix if API or client breaking change
- [ ] confirmed all author checklist items have been addressed
- [ ] reviewed state machine logic
- [ ] reviewed API design and naming
- [ ] reviewed documentation is accurate
- [ ] reviewed tests and test coverage
- [ ] manually tested (if applicable)
  • Loading branch information
RiccardoM authored Jul 25, 2024
1 parent 18f3538 commit ac2537a
Show file tree
Hide file tree
Showing 24 changed files with 756 additions and 2,266 deletions.
13 changes: 2 additions & 11 deletions proto/milkyway/restaking/v1/genesis.proto
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,6 @@ message GenesisState {
// Params defines the parameters of the module.
Params params = 1 [ (gogoproto.nullable) = false ];

// PoolDelegations represents the delegations to pools.
repeated PoolDelegation pools_delegations = 2
[ (gogoproto.nullable) = false ];

// ServiceDelegations represents the delegations to services.
repeated ServiceDelegation services_delegations = 3
[ (gogoproto.nullable) = false ];

// OperatorDelegations represents the delegations to operators.
repeated OperatorDelegation operators_delegations = 4
[ (gogoproto.nullable) = false ];
// Delegations represents the delegations.
repeated Delegation delegations = 2 [ (gogoproto.nullable) = false ];
}
101 changes: 22 additions & 79 deletions proto/milkyway/restaking/v1/models.proto
Original file line number Diff line number Diff line change
Expand Up @@ -8,107 +8,50 @@ import "cosmos/base/v1beta1/coin.proto";

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

// PoolDelegation represents the bond with tokens held by an account with a
// given pool. It is owned by one delegator, and is associated with a pool.
message PoolDelegation {
option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;

// UserAddress is the encoded address of the user.
string user_address = 1 [ (cosmos_proto.scalar) = "cosmos.AddressString" ];

// PoolID is the id of the pool.
uint32 pool_id = 2 [ (gogoproto.customname) = "PoolID" ];

// Shares define the delegation shares received.
string shares = 3 [
(cosmos_proto.scalar) = "cosmos.Dec",
(gogoproto.customtype) = "cosmossdk.io/math.LegacyDec",
(gogoproto.nullable) = false
];
// DelegationType defines the type of delegation.
enum DelegationType {
option (gogoproto.goproto_enum_prefix) = false;

DELEGATION_TYPE_UNSPECIFIED = 0;
DELEGATION_TYPE_POOL = 1;
DELEGATION_TYPE_OPERATOR = 2;
DELEGATION_TYPE_SERVICE = 3;
}

// PoolDelegationResponse is equivalent to PoolDelegation except that it
// contains a balance in addition to shares which is more suitable for client
// responses.
message PoolDelegationResponse {
option (gogoproto.equal) = false;

PoolDelegation delegation = 1
[ (gogoproto.nullable) = false, (amino.dont_omitempty) = true ];

cosmos.base.v1beta1.Coin balance = 2
[ (gogoproto.nullable) = false, (amino.dont_omitempty) = true ];
}

// OperatorDelegation represents the bond with tokens held by an account with a
// given operator. It is owned by one delegator, and is associated with a
// operator.
message OperatorDelegation {
// Delegation represents the bond with tokens held by an account with a
// given target.
message Delegation {
option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;

// UserAddress is the encoded address of the user.
string user_address = 1 [ (cosmos_proto.scalar) = "cosmos.AddressString" ];

// OperatorID is the id of the operator.
uint32 operator_id = 2 [ (gogoproto.customname) = "OperatorID" ];

// Shares define the delegation shares received.
repeated cosmos.base.v1beta1.DecCoin shares = 3 [
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.DecCoins",
(gogoproto.nullable) = false
];
}

// OperatorDelegationResponse is equivalent to OperatorDelegation except that it
// contains a balance in addition to shares which is more suitable for client
// responses.
message OperatorDelegationResponse {
option (gogoproto.equal) = false;

OperatorDelegation delegation = 1
[ (gogoproto.nullable) = false, (amino.dont_omitempty) = true ];

repeated cosmos.base.v1beta1.Coin balance = 2 [
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins",
(gogoproto.nullable) = false,
(amino.dont_omitempty) = true
];
}

// ServiceDelegation represents the bond with tokens held by an account with a
// given service. It is owned by one delegator, and is associated with a
// service.
message ServiceDelegation {
option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;
// Type is the type of delegation.
DelegationType type = 1;

// UserAddress is the encoded address of the user.
string user_address = 1 [ (cosmos_proto.scalar) = "cosmos.AddressString" ];
string user_address = 2 [ (cosmos_proto.scalar) = "cosmos.AddressString" ];

// ServiceID is the id of the service.
uint32 service_id = 2 [ (gogoproto.customname) = "ServiceID" ];
// TargetID is the id of the target to which the delegation is associated
// (pool, operator, service).
uint32 target_id = 3 [ (gogoproto.customname) = "TargetID" ];

// Shares define the delegation shares received.
repeated cosmos.base.v1beta1.DecCoin shares = 3 [
repeated cosmos.base.v1beta1.DecCoin shares = 4 [
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.DecCoins",
(gogoproto.nullable) = false
];
}

// ServiceDelegationResponse is equivalent to ServiceDelegation except that it
// DelegationResponse is equivalent to Delegation except that it
// contains a balance in addition to shares which is more suitable for client
// responses.
message ServiceDelegationResponse {
message DelegationResponse {
option (gogoproto.equal) = false;

ServiceDelegation delegation = 1
Delegation delegation = 1
[ (gogoproto.nullable) = false, (amino.dont_omitempty) = true ];

repeated cosmos.base.v1beta1.Coin balance = 2 [
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins",
(gogoproto.nullable) = false,
(amino.dont_omitempty) = true
(gogoproto.nullable) = false
];
}
24 changes: 9 additions & 15 deletions proto/milkyway/restaking/v1/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -171,8 +171,7 @@ message QueryPoolDelegationsRequest {
// RPC method.
message QueryPoolDelegationsResponse {
// Delegations is the list of delegations
repeated PoolDelegationResponse delegations = 1
[ (gogoproto.nullable) = false ];
repeated DelegationResponse delegations = 1 [ (gogoproto.nullable) = false ];

// Pagination defines the pagination in the response.
cosmos.base.query.v1beta1.PageResponse pagination = 2;
Expand All @@ -193,7 +192,7 @@ message QueryPoolDelegationRequest {
// method.
message QueryPoolDelegationResponse {
// Delegation is the delegation
PoolDelegationResponse delegation = 1 [ (gogoproto.nullable) = false ];
DelegationResponse delegation = 1 [ (gogoproto.nullable) = false ];
}

// QueryOperatorDelegationsRequest is request type for the
Expand All @@ -210,8 +209,7 @@ message QueryOperatorDelegationsRequest {
// Query/OperatorDelegations RPC method.
message QueryOperatorDelegationsResponse {
// Delegations is the list of delegations
repeated OperatorDelegationResponse delegations = 1
[ (gogoproto.nullable) = false ];
repeated DelegationResponse delegations = 1 [ (gogoproto.nullable) = false ];

// Pagination defines the pagination in the response.
cosmos.base.query.v1beta1.PageResponse pagination = 2;
Expand All @@ -232,7 +230,7 @@ message QueryOperatorDelegationRequest {
// Query/OperatorDelegation RPC method.
message QueryOperatorDelegationResponse {
// Delegation is the delegation
OperatorDelegationResponse delegation = 1 [ (gogoproto.nullable) = false ];
DelegationResponse delegation = 1 [ (gogoproto.nullable) = false ];
}

// QueryServiceDelegationsRequest is request type for the
Expand All @@ -249,8 +247,7 @@ message QueryServiceDelegationsRequest {
// Query/ServiceDelegations RPC method.
message QueryServiceDelegationsResponse {
// Delegations is the list of delegations
repeated ServiceDelegationResponse delegations = 1
[ (gogoproto.nullable) = false ];
repeated DelegationResponse delegations = 1 [ (gogoproto.nullable) = false ];

// Pagination defines the pagination in the response.
cosmos.base.query.v1beta1.PageResponse pagination = 2;
Expand All @@ -271,7 +268,7 @@ message QueryServiceDelegationRequest {
// Query/ServiceDelegation RPC method.
message QueryServiceDelegationResponse {
// Delegation is the delegation
ServiceDelegationResponse delegation = 1 [ (gogoproto.nullable) = false ];
DelegationResponse delegation = 1 [ (gogoproto.nullable) = false ];
}

// QueryDelegatorPoolDelegationsRequest is request type for the
Expand All @@ -289,8 +286,7 @@ message QueryDelegatorPoolDelegationsRequest {
// Query/DelegatorPoolDelegations RPC method.
message QueryDelegatorPoolDelegationsResponse {
// Delegations is the list of delegations
repeated PoolDelegationResponse delegations = 1
[ (gogoproto.nullable) = false ];
repeated DelegationResponse delegations = 1 [ (gogoproto.nullable) = false ];

// Pagination defines the pagination in the response.
cosmos.base.query.v1beta1.PageResponse pagination = 2;
Expand All @@ -311,8 +307,7 @@ message QueryDelegatorOperatorDelegationsRequest {
// Query/DelegatorOperatorDelegations RPC method.
message QueryDelegatorOperatorDelegationsResponse {
// Delegations is the list of delegations
repeated OperatorDelegationResponse delegations = 1
[ (gogoproto.nullable) = false ];
repeated DelegationResponse delegations = 1 [ (gogoproto.nullable) = false ];

// Pagination defines the pagination in the response.
cosmos.base.query.v1beta1.PageResponse pagination = 2;
Expand All @@ -333,8 +328,7 @@ message QueryDelegatorServiceDelegationsRequest {
// Query/DelegatorServiceDelegations RPC method.
message QueryDelegatorServiceDelegationsResponse {
// Delegations is the list of delegations
repeated ServiceDelegationResponse delegations = 1
[ (gogoproto.nullable) = false ];
repeated DelegationResponse delegations = 1 [ (gogoproto.nullable) = false ];

// Pagination defines the pagination in the response.
cosmos.base.query.v1beta1.PageResponse pagination = 2;
Expand Down
73 changes: 19 additions & 54 deletions x/restaking/keeper/alias_functions.go
Original file line number Diff line number Diff line change
@@ -1,99 +1,64 @@
package keeper

import (
"fmt"

storetypes "cosmossdk.io/store/types"
sdk "github.com/cosmos/cosmos-sdk/types"

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

// GetAllPoolDelegations returns all the pool delegations
func (k *Keeper) GetAllPoolDelegations(ctx sdk.Context) []types.PoolDelegation {
func (k *Keeper) GetAllPoolDelegations(ctx sdk.Context) []types.Delegation {
store := ctx.KVStore(k.storeKey)
iterator := store.Iterator(types.PoolDelegationPrefix, storetypes.PrefixEndBytes(types.PoolDelegationPrefix))
defer iterator.Close()

var delegations []types.PoolDelegation
var delegations []types.Delegation
for ; iterator.Valid(); iterator.Next() {
delegation := types.MustUnmarshalPoolDelegation(k.cdc, iterator.Value())
delegation := types.MustUnmarshalDelegation(k.cdc, iterator.Value())
delegations = append(delegations, delegation)
}

return delegations
}

// GetAllDelegatorPoolDelegations returns all the pool delegations of a given delegator
func (k *Keeper) GetAllDelegatorPoolDelegations(ctx sdk.Context, delegator string) []types.PoolDelegation {
// GetAllOperatorDelegations returns all the operator delegations
func (k *Keeper) GetAllOperatorDelegations(ctx sdk.Context) []types.Delegation {
store := ctx.KVStore(k.storeKey)
delegatorPrefixKey := types.UserPoolDelegationsStorePrefix(delegator)

iterator := store.Iterator(delegatorPrefixKey, storetypes.PrefixEndBytes(delegatorPrefixKey)) // Smallest to largest
iterator := store.Iterator(types.OperatorDelegationPrefix, storetypes.PrefixEndBytes(types.OperatorDelegationPrefix))
defer iterator.Close()

var delegations []types.PoolDelegation
var delegations []types.Delegation
for ; iterator.Valid(); iterator.Next() {
delegation := types.MustUnmarshalPoolDelegation(k.cdc, iterator.Value())
delegation := types.MustUnmarshalDelegation(k.cdc, iterator.Value())
delegations = append(delegations, delegation)
}

return delegations
}

// GetPoolDelegations returns all the delegations to a given pool
func (k *Keeper) GetPoolDelegations(ctx sdk.Context, poolID uint32) ([]types.PoolDelegation, error) {
store := ctx.KVStore(k.storeKey)
prefix := types.DelegationsByPoolIDStorePrefix(poolID)
iterator := store.Iterator(prefix, storetypes.PrefixEndBytes(prefix))
defer iterator.Close()

var delegations []types.PoolDelegation
for ; iterator.Valid(); iterator.Next() {
_, delegatorAddress, err := types.ParseDelegationsByPoolIDKey(iterator.Key())
if err != nil {
return nil, err
}

delegation, found := k.GetPoolDelegation(ctx, poolID, delegatorAddress)
if !found {
return nil, fmt.Errorf("delegation not found for pool %d and delegator %s", poolID, delegatorAddress)
}

delegations = append(delegations, delegation)
}

return delegations, nil
}

// --------------------------------------------------------------------------------------------------------------------

func (k *Keeper) GetAllOperatorDelegations(ctx sdk.Context) []types.OperatorDelegation {
// GetAllServiceDelegations returns all the service delegations
func (k *Keeper) GetAllServiceDelegations(ctx sdk.Context) []types.Delegation {
store := ctx.KVStore(k.storeKey)
iterator := store.Iterator(types.OperatorDelegationPrefix, storetypes.PrefixEndBytes(types.OperatorDelegationPrefix))
iterator := store.Iterator(types.ServiceDelegationPrefix, storetypes.PrefixEndBytes(types.ServiceDelegationPrefix))
defer iterator.Close()

var delegations []types.OperatorDelegation
var delegations []types.Delegation
for ; iterator.Valid(); iterator.Next() {
delegation := types.MustUnmarshalOperatorDelegation(k.cdc, iterator.Value())
delegation := types.MustUnmarshalDelegation(k.cdc, iterator.Value())
delegations = append(delegations, delegation)
}

return delegations
}

// --------------------------------------------------------------------------------------------------------------------

func (k *Keeper) GetAllServiceDelegations(ctx sdk.Context) []types.ServiceDelegation {
store := ctx.KVStore(k.storeKey)
iterator := store.Iterator(types.ServiceDelegationPrefix, storetypes.PrefixEndBytes(types.ServiceDelegationPrefix))
defer iterator.Close()
// GetAllDelegations returns all the delegations
func (k *Keeper) GetAllDelegations(ctx sdk.Context) []types.Delegation {
var delegations []types.Delegation

var delegations []types.ServiceDelegation
for ; iterator.Valid(); iterator.Next() {
delegation := types.MustUnmarshalServiceDelegation(k.cdc, iterator.Value())
delegations = append(delegations, delegation)
}
delegations = append(delegations, k.GetAllPoolDelegations(ctx)...)
delegations = append(delegations, k.GetAllOperatorDelegations(ctx)...)
delegations = append(delegations, k.GetAllServiceDelegations(ctx)...)

return delegations
}
Loading

0 comments on commit ac2537a

Please sign in to comment.