Skip to content

Commit

Permalink
chore(staking): api and error codes (#445)
Browse files Browse the repository at this point in the history
remove useless api and enhance event processing error codes

issue: none

---------

Signed-off-by: lutty <[email protected]>
Co-authored-by: haodi <[email protected]>
Co-authored-by: lutty <[email protected]>
  • Loading branch information
3 people authored Dec 19, 2024
1 parent e9da1b4 commit cd8a23d
Show file tree
Hide file tree
Showing 12 changed files with 2,190 additions and 1,401 deletions.
2,023 changes: 1,111 additions & 912 deletions client/server/README.md

Large diffs are not rendered by default.

1,381 changes: 992 additions & 389 deletions client/server/api.swagger.yaml

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion client/server/bank.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//nolint:wrapcheck // The api server is our server, so we don't need to wrap it
//nolint:wrapcheck,dupl // The api server is our server, so we don't need to wrap it
package server

import (
Expand Down
46 changes: 1 addition & 45 deletions client/server/distribution.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
//nolint:wrapcheck // The api server is our server, so we don't need to wrap it.
//nolint:wrapcheck,dupl // The api server is our server, so we don't need to wrap it.
package server

import (
"errors"
"net/http"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/query"
"github.com/cosmos/cosmos-sdk/x/distribution/keeper"
distributiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
Expand All @@ -21,7 +19,6 @@ func (s *Server) initDistributionRoute() {
s.httpMux.HandleFunc("/distribution/validators/{validator_address}/commission", utils.SimpleWrap(s.aminoCodec, s.GetValidatorCommissionByValidatorAddress))
s.httpMux.HandleFunc("/distribution/validators/{validator_address}/outstanding_rewards", utils.SimpleWrap(s.aminoCodec, s.GetValidatorOutstandingRewardsByValidatorAddress))
s.httpMux.HandleFunc("/distribution/validators/{validator_address}/slashes", utils.AutoWrap(s.aminoCodec, s.GetValidatorSlashesByValidatorAddress))
s.httpMux.HandleFunc("/distribution/all_validators/outstanding_rewards", utils.AutoWrap(s.aminoCodec, s.GetAllValidatorOutstandingRewards))

s.httpMux.HandleFunc("/distribution/delegators/{delegator_address}/validators", utils.SimpleWrap(s.aminoCodec, s.GetDistributionValidatorsByDelegatorAddress))
s.httpMux.HandleFunc("/distribution/delegators/{delegator_address}/rewards", utils.SimpleWrap(s.aminoCodec, s.GetDelegatorRewardsByDelegatorAddress))
Expand Down Expand Up @@ -97,47 +94,6 @@ func (s *Server) GetValidatorOutstandingRewardsByValidatorAddress(r *http.Reques
return queryResp, nil
}

// GetAllValidatorOutstandingRewards queries rewards of all validators.
func (s *Server) GetAllValidatorOutstandingRewards(req *getAllValidatorOutstandingRewardsRequest, r *http.Request) (resp any, err error) {
if req.To-req.From > 100 {
return nil, errors.New("search max 100 blocks")
}

curBlock, err := s.cl.Block(r.Context(), nil)
if err != nil {
return nil, errors.Join(errors.New("curbock fetch fail"), err)
}

querier := keeper.NewQuerier(s.store.GetDistrKeeper())
result := make([]*getAllValidatorOutstandingRewardsRequestBlockResults, 0)

for i := req.From; i < min(req.To, curBlock.Block.Height); i++ {
queryContext, err := s.store.CreateQueryContext(i, false)
if err != nil {
return nil, errors.Join(errors.New("create query context fail"), err)
}

blockResult := &getAllValidatorOutstandingRewardsRequestBlockResults{
Height: i,
Validators: make(map[string]sdk.DecCoins),
}
//nolint: contextcheck // false positive
querier.IterateValidatorOutstandingRewards(queryContext, func(val sdk.ValAddress, rewards distributiontypes.ValidatorOutstandingRewards) (stop bool) {
if len(rewards.Rewards) > 0 {
blockResult.Validators[val.String()] = rewards.Rewards
}

return false
})

if len(blockResult.Validators) > 0 {
result = append(result, blockResult)
}
}

return result, nil
}

// GetValidatorSlashesByValidatorAddress queries slash events of a validator.
func (s *Server) GetValidatorSlashesByValidatorAddress(req *getValidatorSlashesByValidatorAddressRequest, r *http.Request) (resp any, err error) {
queryContext, err := s.createQueryContextByHeader(r)
Expand Down
14 changes: 0 additions & 14 deletions client/server/payload.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
package server

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

type pagination struct {
Key string `mapstructure:"key"`
Offset uint64 `mapstructure:"offset"`
Expand Down Expand Up @@ -50,16 +46,6 @@ type getDenomOwnersByQueryRequest struct {
Pagination pagination `mapstructure:"pagination"`
}

type getAllValidatorOutstandingRewardsRequest struct {
From int64 `mapstructure:"from"`
To int64 `mapstructure:"to"`
}

type getAllValidatorOutstandingRewardsRequestBlockResults struct {
Height int64 `json:"height"`
Validators map[string]sdk.DecCoins `json:"validators"`
}

type getValidatorSlashesByValidatorAddressRequest struct {
StartingHeight uint64 `mapstructure:"starting_height"`
EndingHeight uint64 `mapstructure:"ending_height"`
Expand Down
18 changes: 15 additions & 3 deletions client/x/evmstaking/keeper/redelegation.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,12 +138,24 @@ func (k Keeper) ProcessRedelegate(ctx context.Context, ev *bindings.IPTokenStaki
depositorAddr.String(), validatorSrcAddr.String(), validatorDstAddr.String(),
ev.DelegationId.String(), amountCoin,
)

_, err = skeeper.NewMsgServerImpl(k.stakingKeeper.(*skeeper.Keeper)).BeginRedelegate(cachedCtx, msg)
if err != nil {
switch {
case errors.Is(err, stypes.ErrSelfRedelegation):
return errors.WrapErrWithCode(errors.SelfRedelegation, err)
case errors.Is(err, stypes.ErrNoValidatorFound):
return errors.WrapErrWithCode(errors.ValidatorNotFound, err)
case errors.Is(err, stypes.ErrTokenTypeMismatch):
return errors.WrapErrWithCode(errors.TokenTypeMismatch, err)
case errors.Is(err, stypes.ErrNoDelegation):
return errors.WrapErrWithCode(errors.DelegationNotFound, err)
case errors.Is(err, stypes.ErrNoPeriodDelegation):
return errors.WrapErrWithCode(errors.PeriodDelegationNotFound, err)
case err != nil:
return errors.Wrap(err, "failed to begin redelegation")
default:
return nil
}

return nil
}

func (k Keeper) ParseRedelegateLog(ethLog ethtypes.Log) (*bindings.IPTokenStakingRedelegate, error) {
Expand Down
12 changes: 10 additions & 2 deletions client/x/evmstaking/keeper/unjail.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"cosmossdk.io/collections"

sdk "github.com/cosmos/cosmos-sdk/types"
slashtypes "github.com/cosmos/cosmos-sdk/x/slashing/types"
ethtypes "github.com/ethereum/go-ethereum/core/types"

"github.com/piplabs/story/client/x/evmstaking/types"
Expand Down Expand Up @@ -78,8 +79,15 @@ func (k Keeper) ProcessUnjail(ctx context.Context, ev *bindings.IPTokenStakingUn
}
}

err = k.slashingKeeper.Unjail(cachedCtx, valAddr)
if err != nil {
if err = k.slashingKeeper.Unjail(cachedCtx, valAddr); errors.Is(err, slashtypes.ErrNoValidatorForAddress) {
return errors.WrapErrWithCode(errors.ValidatorNotFound, err)
} else if errors.Is(err, slashtypes.ErrMissingSelfDelegation) {
return errors.WrapErrWithCode(errors.MissingSelfDelegation, err)
} else if errors.Is(err, slashtypes.ErrValidatorNotJailed) {
return errors.WrapErrWithCode(errors.ValidatorNotJailed, err)
} else if errors.Is(err, slashtypes.ErrValidatorJailed) {
return errors.WrapErrWithCode(errors.ValidatorStillJailed, err)
} else if err != nil {
return errors.Wrap(err, "unjail")
}

Expand Down
4 changes: 3 additions & 1 deletion client/x/evmstaking/keeper/update_commission.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@ func (k Keeper) ProcessUpdateValidatorCommission(ctx context.Context, ev *bindin

validatorAddr := sdk.ValAddress(validatorPubkey.Address().Bytes())
validator, err := k.stakingKeeper.GetValidator(cachedCtx, validatorAddr)
if err != nil {
if errors.Is(err, stypes.ErrNoValidatorFound) {
return errors.WrapErrWithCode(errors.ValidatorNotFound, err)
} else if err != nil {
return errors.Wrap(err, "get validator")
}

Expand Down
11 changes: 3 additions & 8 deletions client/x/evmstaking/keeper/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,13 +96,6 @@ func (k Keeper) ProcessCreateValidator(ctx context.Context, ev *bindings.IPToken
}
skeeperMsgServer := skeeper.NewMsgServerImpl(evmstakingSKeeper)

if _, err = k.stakingKeeper.GetValidator(cachedCtx, validatorAddr); err == nil {
return errors.WrapErrWithCode(errors.ValidatorAlreadyExists, errors.New("validator already exists"))
} else if !errors.Is(err, stypes.ErrNoValidatorFound) {
// Either the validator does not exist, or unknown error.
return errors.Wrap(err, "get validator")
}

moniker := ev.Moniker
if moniker == "" {
moniker = validatorAddr.String() // use validator address as moniker if not provided
Expand Down Expand Up @@ -158,7 +151,9 @@ func (k Keeper) ProcessCreateValidator(ctx context.Context, ev *bindings.IPToken
return errors.Wrap(err, "create stake coin for depositor: send coins")
}

if _, err = skeeperMsgServer.CreateValidator(cachedCtx, msg); errors.Is(err, stypes.ErrCommissionLTMinRate) {
if _, err := skeeperMsgServer.CreateValidator(cachedCtx, msg); errors.Is(err, stypes.ErrValidatorOwnerExists) {
return errors.WrapErrWithCode(errors.ValidatorAlreadyExists, err)
} else if errors.Is(err, stypes.ErrCommissionLTMinRate) {
return errors.WrapErrWithCode(errors.InvalidCommissionRate, err)
} else if errors.Is(err, stypes.ErrMinSelfDelegationBelowMinDelegation) {
return errors.WrapErrWithCode(errors.InvalidMinSelfDelegation, err)
Expand Down
6 changes: 5 additions & 1 deletion client/x/evmstaking/keeper/withdraw.go
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,11 @@ func (k Keeper) ProcessWithdraw(ctx context.Context, ev *bindings.IPTokenStaking

// Undelegate from the validator (validator existence is checked in ValidateUnbondAmount)
resp, err := skeeper.NewMsgServerImpl(k.stakingKeeper.(*skeeper.Keeper)).Undelegate(cachedCtx, msg)
if errors.Is(err, stypes.ErrNoPeriodDelegation) {
if errors.Is(err, stypes.ErrNoValidatorFound) {
return errors.WrapErrWithCode(errors.ValidatorNotFound, err)
} else if errors.Is(err, stypes.ErrNoDelegation) {
return errors.WrapErrWithCode(errors.DelegationNotFound, err)
} else if errors.Is(err, stypes.ErrNoPeriodDelegation) {
return errors.WrapErrWithCode(errors.PeriodDelegationNotFound, err)
} else if err != nil {
return errors.Wrap(err, "undelegate")
Expand Down
10 changes: 2 additions & 8 deletions contracts/script/GenerateAlloc.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -217,16 +217,10 @@ contract GenerateAlloc is Script {
vm.stopPrank();
bytes32 cancellerRole = TimelockController(payable(timelock)).CANCELLER_ROLE();
vm.prank(protocolAdmin);
TimelockController(payable(timelock)).grantRole(
cancellerRole,
canceller
);
TimelockController(payable(timelock)).grantRole(cancellerRole, canceller);
if (!KEEP_TIMELOCK_ADMIN_ROLE) {
bytes32 adminRole = TimelockController(payable(timelock)).DEFAULT_ADMIN_ROLE();
TimelockController(payable(timelock)).renounceRole(
adminRole,
protocolAdmin
);
TimelockController(payable(timelock)).renounceRole(adminRole, protocolAdmin);
}
vm.stopPrank();
vm.startPrank(deployer);
Expand Down
64 changes: 47 additions & 17 deletions lib/errors/codes.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,50 +8,68 @@ type ErrCode uint32

const (
Unspecified ErrCode = 0
InvalidUncmpPubKey ErrCode = 1
ValidatorNotFound ErrCode = 2
ValidatorAlreadyExists ErrCode = 3
InvalidTokenType ErrCode = 4
InvalidPeriodType ErrCode = 5
UnexpectedCondition ErrCode = 1
InvalidUncmpPubKey ErrCode = 2
ValidatorNotFound ErrCode = 3
ValidatorAlreadyExists ErrCode = 4
InvalidTokenType ErrCode = 5
InvalidOperator ErrCode = 6
InvalidCommissionRate ErrCode = 7
InvalidMinSelfDelegation ErrCode = 8
InvalidDelegationAmount ErrCode = 9
PeriodDelegationNotFound ErrCode = 10
InvalidRequest ErrCode = 11
UnexpectedCondition ErrCode = 12
InvalidPeriodType ErrCode = 9
InvalidDelegationAmount ErrCode = 10
DelegationNotFound ErrCode = 11
PeriodDelegationNotFound ErrCode = 12
InvalidRequest ErrCode = 13
SelfRedelegation ErrCode = 14
TokenTypeMismatch ErrCode = 15
MissingSelfDelegation ErrCode = 16
ValidatorNotJailed ErrCode = 17
ValidatorStillJailed ErrCode = 18
)

var (
ErrUnspecified = stderrors.New("unspecified")
ErrUnexpectedCondition = stderrors.New("unexpected_condition")
ErrInvalidUncmpPubKey = stderrors.New("invalid_uncompressed_pubkey")
ErrValidatorNotFound = stderrors.New("validator_not_found")
ErrValidatorAlreadyExists = stderrors.New("validator_already_exists")
ErrInvalidTokenType = stderrors.New("invalid_token_type")
ErrInvalidPeriodType = stderrors.New("invalid_period_type")
ErrInvalidOperator = stderrors.New("invalid_operator")
ErrInvalidCommissionRate = stderrors.New("invalid_commission_rate")
ErrInvalidMinSelfDelegation = stderrors.New("invalid_min_self_delegation")
ErrInvalidPeriodType = stderrors.New("invalid_period_type")
ErrInvalidDelegationAmount = stderrors.New("invalid_delegation_amount")
ErrDelegationNotFound = stderrors.New("delegation_not_found")
ErrPeriodDelegationNotFound = stderrors.New("period_delegation_not_found")
ErrInvalidRequest = stderrors.New("invalid_request")
ErrUnexpectedCondition = stderrors.New("unexpected_condition")
ErrSelfRedelegation = stderrors.New("self_redelegation")
ErrTokenTypeMismatch = stderrors.New("token_type_mismatch")
ErrMissingSelfDelegation = stderrors.New("missing_self_delegation")
ErrValidatorNotJailed = stderrors.New("validator_not_jailed")
ErrValidatorStillJailed = stderrors.New("validator_still_jailed")
)

var codeToErr = map[ErrCode]error{
Unspecified: ErrUnspecified,
UnexpectedCondition: ErrUnexpectedCondition,
InvalidUncmpPubKey: ErrInvalidUncmpPubKey,
ValidatorNotFound: ErrValidatorNotFound,
ValidatorAlreadyExists: ErrValidatorAlreadyExists,
InvalidTokenType: ErrInvalidTokenType,
InvalidPeriodType: ErrInvalidPeriodType,
InvalidOperator: ErrInvalidOperator,
InvalidCommissionRate: ErrInvalidCommissionRate,
InvalidMinSelfDelegation: ErrInvalidMinSelfDelegation,
InvalidPeriodType: ErrInvalidPeriodType,
InvalidDelegationAmount: ErrInvalidDelegationAmount,
DelegationNotFound: ErrDelegationNotFound,
PeriodDelegationNotFound: ErrPeriodDelegationNotFound,
InvalidRequest: ErrInvalidRequest,
UnexpectedCondition: ErrUnexpectedCondition,
SelfRedelegation: ErrSelfRedelegation,
TokenTypeMismatch: ErrTokenTypeMismatch,
MissingSelfDelegation: ErrMissingSelfDelegation,
ValidatorNotJailed: ErrValidatorNotJailed,
ValidatorStillJailed: ErrValidatorStillJailed,
}

func (c ErrCode) String() string {
Expand All @@ -75,6 +93,8 @@ func UnwrapErrCode(err error) ErrCode {
switch {
case stderrors.Is(err, ErrUnspecified):
return Unspecified
case stderrors.Is(err, ErrUnexpectedCondition):
return UnexpectedCondition
case stderrors.Is(err, ErrInvalidUncmpPubKey):
return InvalidUncmpPubKey
case stderrors.Is(err, ErrValidatorNotFound):
Expand All @@ -83,22 +103,32 @@ func UnwrapErrCode(err error) ErrCode {
return ValidatorAlreadyExists
case stderrors.Is(err, ErrInvalidTokenType):
return InvalidTokenType
case stderrors.Is(err, ErrInvalidPeriodType):
return InvalidPeriodType
case stderrors.Is(err, ErrInvalidOperator):
return InvalidOperator
case stderrors.Is(err, ErrInvalidCommissionRate):
return InvalidCommissionRate
case stderrors.Is(err, ErrInvalidMinSelfDelegation):
return InvalidMinSelfDelegation
case stderrors.Is(err, ErrInvalidPeriodType):
return InvalidPeriodType
case stderrors.Is(err, ErrInvalidDelegationAmount):
return InvalidDelegationAmount
case stderrors.Is(err, ErrDelegationNotFound):
return DelegationNotFound
case stderrors.Is(err, ErrPeriodDelegationNotFound):
return PeriodDelegationNotFound
case stderrors.Is(err, ErrInvalidRequest):
return InvalidRequest
case stderrors.Is(err, ErrUnexpectedCondition):
return UnexpectedCondition
case stderrors.Is(err, ErrSelfRedelegation):
return SelfRedelegation
case stderrors.Is(err, ErrTokenTypeMismatch):
return TokenTypeMismatch
case stderrors.Is(err, ErrMissingSelfDelegation):
return MissingSelfDelegation
case stderrors.Is(err, ErrValidatorNotJailed):
return ValidatorNotJailed
case stderrors.Is(err, ErrValidatorStillJailed):
return ValidatorStillJailed
default:
return Unspecified
}
Expand Down

0 comments on commit cd8a23d

Please sign in to comment.