Skip to content

Commit

Permalink
add admin functionality to disable module incase of failure. (#411)
Browse files Browse the repository at this point in the history
* add admin functionality to disable module incase of failure.

* add spec for txn
  • Loading branch information
puneet2019 committed Feb 15, 2023
1 parent a6d1061 commit a1d6641
Show file tree
Hide file tree
Showing 12 changed files with 662 additions and 64 deletions.
12 changes: 12 additions & 0 deletions proto/pstake/lscosmos/v1beta1/msgs.proto
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ service Msg{
rpc JumpStart(MsgJumpStart) returns (MsgJumpStartResponse) {
option (google.api.http).post = "/pstake/lscosmos/v1beta1/JumpStart";
}

rpc ChangeModuleState(MsgChangeModuleState) returns (MsgChangeModuleStateResponse) {
option (google.api.http).post = "/pstake/lscosmos/v1beta1/ChangeModuleState";
}

}

message MsgLiquidStake {
Expand Down Expand Up @@ -86,3 +91,10 @@ message MsgJumpStart {
}

message MsgJumpStartResponse {}

message MsgChangeModuleState {
string pstake_address = 1;
bool module_state = 2;
}

message MsgChangeModuleStateResponse {}
29 changes: 29 additions & 0 deletions x/lscosmos/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package cli

import (
"fmt"
"strconv"
"strings"

"github.com/cosmos/cosmos-sdk/client"
Expand Down Expand Up @@ -34,6 +35,7 @@ func GetTxCmd() *cobra.Command {
NewClaimCmd(),
NewJumpStartCmd(),
NewRecreateICACmd(),
NewChangeModuleStateCmd(),
)

return cmd
Expand Down Expand Up @@ -578,3 +580,30 @@ func NewJumpStartCmd() *cobra.Command {

return cmd
}

func NewChangeModuleStateCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "change-module-state",
Short: "Admin functionality to disable/enable the functionality incase of failures",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {

clientctx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}
moduleState, err := strconv.ParseBool(args[0])
if err != nil {
return err
}
fromAddress := clientctx.GetFromAddress()
msg := types.NewMsgChangeModuleState(fromAddress, moduleState)

return tx.GenerateOrBroadcastTxCLI(clientctx, cmd.Flags(), msg)
},
}

flags.AddTxFlagsToCmd(cmd)

return cmd
}
3 changes: 3 additions & 0 deletions x/lscosmos/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ func NewHandler(k keeper.Keeper) sdk.Handler {
case *types.MsgJumpStart:
res, err := msgServer.JumpStart(sdk.WrapSDKContext(ctx), msg)
return sdk.WrapServiceResult(ctx, res, err)
case *types.MsgChangeModuleState:
res, err := msgServer.ChangeModuleState(sdk.WrapSDKContext(ctx), msg)
return sdk.WrapServiceResult(ctx, res, err)
default:
errMsg := fmt.Sprintf("unrecognized %s message type: %T", types.ModuleName, msg)
return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, errMsg)
Expand Down
33 changes: 33 additions & 0 deletions x/lscosmos/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package keeper
import (
"context"
"fmt"
"strconv"

sdktypes "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
Expand Down Expand Up @@ -518,3 +519,35 @@ func (m msgServer) RecreateICA(goCtx context.Context, msg *types.MsgRecreateICA)
return &types.MsgRecreateICAResponse{}, nil

}

// ChangeModuleState defines an admin method for disabling or re-enabling module state
func (m msgServer) ChangeModuleState(goCtx context.Context, msg *types.MsgChangeModuleState) (*types.MsgChangeModuleStateResponse, error) {
ctx := sdktypes.UnwrapSDKContext(goCtx)

hostChainParams := m.Keeper.GetHostChainParams(ctx)
if hostChainParams.IsEmpty() {
return nil, types.ErrModuleNotInitialised
}
if hostChainParams.PstakeParams.PstakeFeeAddress != msg.PstakeAddress {
return nil, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, fmt.Sprintf("Only admin address is allowed to call this method, current admin address: %s", hostChainParams.PstakeParams.PstakeFeeAddress))
}
moduleState := m.Keeper.GetModuleState(ctx)
if moduleState == msg.ModuleState {
return nil, sdkerrors.Wrap(types.ErrModuleNotInitialised, fmt.Sprintf("currentState: %v", moduleState))
}
m.Keeper.SetModuleState(ctx, msg.ModuleState)

ctx.EventManager().EmitEvents(sdktypes.Events{
sdktypes.NewEvent(
types.EventTypeChangeModuleState,
sdktypes.NewAttribute(types.AttributeChangedModuleState, strconv.FormatBool(msg.ModuleState)),
),
sdktypes.NewEvent(
sdktypes.EventTypeMessage,
sdktypes.NewAttribute(sdktypes.AttributeKeyModule, types.AttributeValueCategory),
sdktypes.NewAttribute(sdktypes.AttributeKeySender, msg.PstakeAddress),
)},
)
return &types.MsgChangeModuleStateResponse{}, nil

}
19 changes: 19 additions & 0 deletions x/lscosmos/spec/06_messages.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,3 +148,22 @@ Inputs for this message :
```
$ pstaked tx lscosmos recreate-ica --from <from_address> --chain-id <chain-id> --keyring-backend <keyring_backend>
```

### MsgChangeModuleState

ChangeModuleState is a transaction for disabling/ reenabling the module.

It performs the following operations :

- Checks if the module was initiated before, if no returns error
- Checks if the sender is admin
- Checks if the state is being changed.

Inputs for this message :

- `PstakeAddress` : Address from which this transaction is being sent (should be pstakeAddress).
- `ModuleState` : The boolean value true/false to which the module state is to be set.

```
$ pstaked tx lscosmos change-module-state false --from <from_address> --chain-id <chain-id> --keyring-backend <keyring_backend>
```
2 changes: 2 additions & 0 deletions x/lscosmos/types/codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {
cdc.RegisterConcrete(&MsgClaim{}, "cosmos/MsgClaim", nil)
cdc.RegisterConcrete(&MsgRecreateICA{}, "cosmos/MsgRecreateICA", nil)
cdc.RegisterConcrete(&MsgJumpStart{}, "cosmos/MsgJumpStart", nil)
cdc.RegisterConcrete(&MsgChangeModuleState{}, "cosmos/MsgChangeModuleState", nil)
}

// RegisterInterfaces registers the x/lscosmos interfaces types with the interface registry
Expand All @@ -33,6 +34,7 @@ func RegisterInterfaces(registry cdctypes.InterfaceRegistry) {
&MsgClaim{},
&MsgRecreateICA{},
&MsgJumpStart{},
&MsgChangeModuleState{},
) // add the structs that implements sdk.Msg interface

registry.RegisterImplementations((*govtypes.Content)(nil),
Expand Down
2 changes: 2 additions & 0 deletions x/lscosmos/types/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,6 @@ var (
ErrEqualBaseAndMintDenom = sdkerrors.Register(ModuleName, 87, "BaseDenom and mintDenom cannot be same")
ErrInsufficientFundsToUndelegate = sdkerrors.Register(ModuleName, 88, "undelegation amount greater than already staked")
ErrInvalidMintDenom = sdkerrors.Register(ModuleName, 89, "InvalidMintDenom, MintDenom should be stk/BaseDenom")
ErrModuleNotInitialised = sdkerrors.Register(ModuleName, 90, "ErrModuleNotInitialised, Module was never initialised")
ErrModuleAlreadyInExpectedState = sdkerrors.Register(ModuleName, 91, "ModuleAlreadyInExpectedState, Module is already in expected state")
)
18 changes: 10 additions & 8 deletions x/lscosmos/types/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ package types

// IBC events
const (
EventTypePacket = "ics27_packet"
EventTypeTimeout = "timeout"
EventTypeLiquidStake = "liquid-stake"
EventTypeRedeem = "redeem"
EventTypeLiquidUnstake = "liquid-unstake"
EventTypeClaim = "claim"
EventTypeJumpStart = "jump-start"
EventTypeRecreateICA = "recreate-ica"
EventTypePacket = "ics27_packet"
EventTypeTimeout = "timeout"
EventTypeLiquidStake = "liquid-stake"
EventTypeRedeem = "redeem"
EventTypeLiquidUnstake = "liquid-unstake"
EventTypeClaim = "claim"
EventTypeJumpStart = "jump-start"
EventTypeRecreateICA = "recreate-ica"
EventTypeChangeModuleState = "change-module-state"
// this line is used by starport scaffolding # ibc/packet/event

AttributeKeyAckSuccess = "success"
Expand All @@ -28,5 +29,6 @@ const (
AttributeFromAddress = "from-address"
AttributeRecreateDelegationICA = "recreate-delegation-ica"
AttributeRecreateRewardsICA = "recreate-rewards-ica"
AttributeChangedModuleState = "module-state"
AttributeValueCategory = ModuleName
)
3 changes: 3 additions & 0 deletions x/lscosmos/types/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ const (
// MsgTypeJumpStart is the type of message Jump start
MsgTypeJumpStart = "msg_jump_start"

// MsgTypeChangeModuleState is the type of message Change Module State
MsgTypeChangeModuleState = "msg_change_module_state"

// DepositModuleAccount DepositModuleAccountName
DepositModuleAccount = ModuleName + "_pstake_deposit_account"

Expand Down
40 changes: 40 additions & 0 deletions x/lscosmos/types/msgs.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ var (
_ sdk.Msg = &MsgClaim{}
_ sdk.Msg = &MsgRecreateICA{}
_ sdk.Msg = &MsgJumpStart{}
_ sdk.Msg = &MsgChangeModuleState{}
)

// NewMsgLiquidStake returns a new MsgLiquidStake
Expand Down Expand Up @@ -304,3 +305,42 @@ func (m *MsgJumpStart) GetSigners() []sdk.AccAddress {
}
return []sdk.AccAddress{acc}
}

// NewMsgChangeModuleState returns a new MsgChangeModuleState
//
//nolint:interfacer
func NewMsgChangeModuleState(address sdk.AccAddress, moduleState bool) *MsgChangeModuleState {
return &MsgChangeModuleState{
PstakeAddress: address.String(),
ModuleState: moduleState,
}
}

// Route should return the name of the module
func (m *MsgChangeModuleState) Route() string { return RouterKey }

// Type should return the action
func (m *MsgChangeModuleState) Type() string { return MsgTypeChangeModuleState }

// ValidateBasic performs stateless checks
func (m *MsgChangeModuleState) ValidateBasic() error {
if _, err := sdk.AccAddressFromBech32(m.PstakeAddress); err != nil {
return sdkErrors.Wrap(sdkErrors.ErrInvalidAddress, m.PstakeAddress)
}

return nil
}

// GetSignBytes encodes the message for signing
func (m *MsgChangeModuleState) GetSignBytes() []byte {
return sdk.MustSortJSON(AminoCdc.MustMarshalJSON(m))
}

// GetSigners defines whose signature is required
func (m *MsgChangeModuleState) GetSigners() []sdk.AccAddress {
acc, err := sdk.AccAddressFromBech32(m.PstakeAddress)
if err != nil {
panic(err)
}
return []sdk.AccAddress{acc}
}
Loading

0 comments on commit a1d6641

Please sign in to comment.