Skip to content

Commit

Permalink
fix ibc routing issues, and fix portID representation. (#704)
Browse files Browse the repository at this point in the history
  • Loading branch information
puneet2019 authored Dec 18, 2023
1 parent 1893c34 commit ba2aa32
Show file tree
Hide file tree
Showing 10 changed files with 147 additions and 66 deletions.
4 changes: 3 additions & 1 deletion app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -512,14 +512,16 @@ func NewpStakeApp(
icaHostStack = ibcfee.NewIBCMiddleware(icaHostStack, app.IBCFeeKeeper)

var icaControllerStack porttypes.IBCModule = liquidStakeIBCModule
icaControllerStack = ratesync.NewIBCModule(*app.RatesyncKeeper, icaHostStack)
icaControllerStack = icacontroller.NewIBCMiddleware(icaControllerStack, app.ICAControllerKeeper)

ibcRouter := porttypes.NewRouter()
ibcRouter.
AddRoute(ibctransfertypes.ModuleName, transferStack).
AddRoute(icahosttypes.SubModuleName, icaHostStack).
AddRoute(icacontrollertypes.SubModuleName, icaControllerStack).
AddRoute(liquidstakeibctypes.ModuleName, icaControllerStack)
AddRoute(liquidstakeibctypes.ModuleName, icaControllerStack).
AddRoute(ratesynctypes.ModuleName, icaControllerStack)

app.IBCKeeper.SetRouter(ibcRouter)

Expand Down
2 changes: 1 addition & 1 deletion x/liquidstakeibc/keeper/ibc.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ func (k *Keeper) OnChanOpenAck(
hc.RewardsAccount.Owner = portOwner
hc.RewardsAccount.ChannelState = types.ICAAccount_ICA_CHANNEL_CREATED
default:
k.Logger(ctx).Error("Unrecognised ICA account type for the module", "port-id:", portID, "chain-id", chainID)
k.Logger(ctx).Info("Unrecognised ICA account type for the module", "port-id:", portID, "chain-id", chainID)
return nil
}

Expand Down
2 changes: 1 addition & 1 deletion x/ratesync/keeper/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func (k *Keeper) DoRecreateICA(ctx sdk.Context, hc types.HostChain) {
}

// if the channel is closed, and it is not being recreated, recreate it
portID := types.MustICAPortIDfromOwner(hc.IcaAccount.Owner)
portID := types.MustICAPortIDFromOwner(hc.IcaAccount.Owner)
_, isActive := k.icaControllerKeeper.GetOpenActiveChannel(ctx, hc.ConnectionId, portID)
if !isActive {
if err := k.icaControllerKeeper.RegisterInterchainAccount(ctx, hc.ConnectionId, portID, ""); err != nil {
Expand Down
59 changes: 38 additions & 21 deletions x/ratesync/keeper/ibc.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types"
icatypes "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/types"
ibctransfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types"
channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types"
Expand All @@ -17,19 +16,6 @@ import (
"github.com/persistenceOne/pstake-native/v2/x/ratesync/types"
)

func (k *Keeper) OnChanOpenInit(
ctx sdk.Context,
order channeltypes.Order,
connectionHops []string,
portID string,
channelID string,
channelCap *capabilitytypes.Capability,
counterparty channeltypes.Counterparty,
version string,
) (string, error) {
return version, nil
}

func (k *Keeper) OnChanOpenAck(
ctx sdk.Context,
portID string,
Expand All @@ -49,8 +35,8 @@ func (k *Keeper) OnChanOpenAck(
return fmt.Errorf("couldn't find address for %s/%s", connID, portID)
}

// get the port owner from the port id
portOwner, err := types.OwnerfromPortID(portID)
// get the port owner from the port id, duplicated check as of ibc-go controller stack
portOwner, err := types.OwnerFromPortID(portID)
if err != nil {
return fmt.Errorf("unable to parse port id %s, err: %v", portID, err)
}
Expand All @@ -61,14 +47,16 @@ func (k *Keeper) OnChanOpenAck(
return fmt.Errorf("unable to get chain id for connection %s: %w", connID, err)
}

id, err := types.IDfromPortID(portID)
id, err := types.IDFromPortID(portID)
if err != nil {
return err
// Port is not related to this module
return nil
}
// get host chain
hc, found := k.GetHostChain(ctx, id)
if !found {
return fmt.Errorf("host chain with id %s is not registered", chainID)
k.Logger(ctx).Info(fmt.Sprintf("host chain with id %s is not registered", id))

Check failure on line 58 in x/ratesync/keeper/ibc.go

View workflow job for this annotation

GitHub Actions / unit-test-coverage

fmt.Sprintf format %s has arg id of wrong type uint64
return nil
}

switch {
Expand Down Expand Up @@ -114,6 +102,18 @@ func (k *Keeper) OnAcknowledgementPacket(
acknowledgement []byte,
relayer sdk.AccAddress,
) error {

id, err := types.IDFromPortID(packet.SourcePort)
if err != nil {
// Port is not related to this module
return nil
}
// get host chain
hc, found := k.GetHostChain(ctx, id)
if !found {
return errorsmod.Wrapf(sdkerrors.ErrNotFound, "host chain with id %s is not present", id)

Check failure on line 114 in x/ratesync/keeper/ibc.go

View workflow job for this annotation

GitHub Actions / unit-test-coverage

cosmossdk.io/errors.Wrapf format %s has arg id of wrong type uint64
}

var ack channeltypes.Acknowledgement
if err := ibctransfertypes.ModuleCdc.UnmarshalJSON(acknowledgement, &ack); err != nil {
return errorsmod.Wrapf(sdkerrors.ErrUnknownRequest, "cannot unmarshal packet acknowledgement: %v", err)
Expand All @@ -125,10 +125,13 @@ func (k *Keeper) OnAcknowledgementPacket(
}

var icaMemo types.ICAMemo
err := json.Unmarshal([]byte(icaPacket.Memo), &icaMemo)
err = json.Unmarshal([]byte(icaPacket.Memo), &icaMemo)
if err != nil {
return err
}
if hc.Id != icaMemo.HostChainId {
return errorsmod.Wrapf(types.ErrInvalid, "host chain ID should match ID in memo")
}
switch resp := ack.Response.(type) {
case *channeltypes.Acknowledgement_Error:
err := k.handleUnsuccessfulAck(ctx, icaPacket, packet, icaMemo)
Expand Down Expand Up @@ -175,17 +178,31 @@ func (k *Keeper) OnTimeoutPacket(
packet channeltypes.Packet,
relayer sdk.AccAddress,
) error {

id, err := types.IDFromPortID(packet.SourcePort)
if err != nil {
// Port is not related to this module
return nil
}
// get host chain
hc, found := k.GetHostChain(ctx, id)
if !found {
return errorsmod.Wrapf(sdkerrors.ErrNotFound, "host chain with id %s is not present", id)

Check failure on line 190 in x/ratesync/keeper/ibc.go

View workflow job for this annotation

GitHub Actions / unit-test-coverage

cosmossdk.io/errors.Wrapf format %s has arg id of wrong type uint64
}
var icaPacket icatypes.InterchainAccountPacketData
if err := icatypes.ModuleCdc.UnmarshalJSON(packet.GetData(), &icaPacket); err != nil {
return errorsmod.Wrapf(sdkerrors.ErrUnknownRequest, "cannot unmarshal ICS-27 tx message data: %v", err)
}

var icaMemo types.ICAMemo
err := json.Unmarshal([]byte(icaPacket.Memo), &icaMemo)
err = json.Unmarshal([]byte(icaPacket.Memo), &icaMemo)
if err != nil {
return err
}

if hc.Id != icaMemo.HostChainId {
return errorsmod.Wrapf(types.ErrInvalid, "host chain ID should match ID in memo")
}
if err := k.handleUnsuccessfulAck(ctx, icaPacket, packet, icaMemo); err != nil {
return err
}
Expand Down
57 changes: 38 additions & 19 deletions x/ratesync/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ import (
"fmt"
wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types"
"github.com/cosmos/gogoproto/proto"
channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types"
"slices"

errorsmod "cosmossdk.io/errors"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
icatypes "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/types"
liquidstakeibctypes "github.com/persistenceOne/pstake-native/v2/x/liquidstakeibc/types"

"github.com/persistenceOne/pstake-native/v2/x/ratesync/types"
Expand Down Expand Up @@ -52,7 +52,7 @@ func (k msgServer) CreateHostChain(goCtx context.Context, msg *types.MsgCreateHo

if msg.HostChain.IcaAccount.Owner == "" {
msg.HostChain.IcaAccount.Owner = types.DefaultPortOwner(id)
}
} // else handled in msg.ValidateBasic()
// register ratesyn ICA
if msg.HostChain.IcaAccount.ChannelState == liquidstakeibctypes.ICAAccount_ICA_CHANNEL_CREATING {
err = k.icaControllerKeeper.RegisterInterchainAccount(ctx, msg.HostChain.ConnectionId, msg.HostChain.IcaAccount.Owner, "")
Expand All @@ -64,16 +64,7 @@ func (k msgServer) CreateHostChain(goCtx context.Context, msg *types.MsgCreateHo
err.Error(),
)
}
} else {
//check for proper address
addr, found := k.icaControllerKeeper.GetInterchainAccountAddress(ctx, msg.HostChain.ConnectionId, types.MustICAPortIDfromOwner(msg.HostChain.IcaAccount.Owner))
if !found {
return nil, errorsmod.Wrapf(icatypes.ErrInterchainAccountNotFound, "no address found for given port, expected %s", msg.HostChain.IcaAccount.Address)
}
if addr != msg.HostChain.IcaAccount.Address {
return nil, errorsmod.Wrapf(sdkerrors.ErrInvalidAddress, "ica address mismatch, expected %s, found %s", msg.HostChain.IcaAccount.Address, addr)
}
}
} // else handled in validate basic (not allowed to create new host chain with previous ICA as portID is default and suffixed by ID

k.SetHostChain(
ctx,
Expand Down Expand Up @@ -112,14 +103,11 @@ func (k msgServer) UpdateHostChain(goCtx context.Context, msg *types.MsgUpdateHo

// only allow enable disable feature && instantiate.
// to change chain-id etc, add delete and create new hostchain with same details
if msg.HostChain.ChainId != oldHC.ChainId {
return nil, errorsmod.Wrapf(types.ErrInvalid, "invalid chainID, chainID cannot be updated, "+
"chainID mismatch got %s, found %s", msg.HostChain.ChainId, oldHC.ChainId)
}
if msg.HostChain.ConnectionId != oldHC.ConnectionId {
return nil, errorsmod.Wrapf(types.ErrInvalid, "invalid connectionID, connectionID cannot be updated, "+
"connectionID mismatch got %s, found %s", msg.HostChain.ConnectionId, oldHC.ConnectionId)
}

if oldHC.IcaAccount.ChannelState != liquidstakeibctypes.ICAAccount_ICA_CHANNEL_CREATED {
return nil, errorsmod.Wrapf(types.ErrInvalid, "invalid ICAAccount state, should already be active")
}
Expand All @@ -136,8 +124,21 @@ func (k msgServer) UpdateHostChain(goCtx context.Context, msg *types.MsgUpdateHo
saveUpdate := func(updates string) (bool, string) {
return true, updates
}

chainID, err := k.GetChainID(ctx, msg.HostChain.ConnectionId)
if err != nil {
return nil, errorsmod.Wrapf(sdkerrors.ErrNotFound, "chain id not found for connection \"%s\": \"%s\"", msg.HostChain.ConnectionId, err)
}
if chainID != msg.HostChain.ChainId {
return nil, errorsmod.Wrapf(sdkerrors.ErrInvalidChainID, "chain id does not match connection-chainID input \"%s\": found\"%s\"", msg.HostChain.ChainId, chainID)
}
if msg.HostChain.ChainId != oldHC.ChainId {
oldHC.ChainId = msg.HostChain.ChainId
isOneUpdated, updateStr = saveUpdate(fmt.Sprintf("updates host chain chainID %v to %v \n", oldHC.ChainId, msg.HostChain.ChainId))
}

//allow only one feature update per tx.
if !msg.HostChain.Features.LiquidStakeIBC.Equals(oldHC.Features.LiquidStakeIBC) {
if !isOneUpdated && !msg.HostChain.Features.LiquidStakeIBC.Equals(oldHC.Features.LiquidStakeIBC) {
if oldHC.Features.LiquidStakeIBC.Instantiation == types.InstantiationState_INSTANTIATION_NOT_INITIATED {
// allow to add details and instantiate or just save if trying to recover.
switch msg.HostChain.Features.LiquidStakeIBC.Instantiation {
Expand Down Expand Up @@ -188,7 +189,7 @@ func (k msgServer) UpdateHostChain(goCtx context.Context, msg *types.MsgUpdateHo
}
isOneUpdated, updateStr = saveUpdate(fmt.Sprintf("updates LiquidStakeIBC feature from %v to %v \n", oldHC.Features.LiquidStakeIBC, msg.HostChain.Features.LiquidStakeIBC))
}
if isOneUpdated && !msg.HostChain.Features.LiquidStake.Equals(oldHC.Features.LiquidStake) {
if !isOneUpdated && !msg.HostChain.Features.LiquidStake.Equals(oldHC.Features.LiquidStake) {
if oldHC.Features.LiquidStake.Instantiation == types.InstantiationState_INSTANTIATION_NOT_INITIATED {
// allow to add details and instantiate or just save if trying to recover.
switch msg.HostChain.Features.LiquidStake.Instantiation {
Expand Down Expand Up @@ -239,7 +240,7 @@ func (k msgServer) UpdateHostChain(goCtx context.Context, msg *types.MsgUpdateHo
}
isOneUpdated, updateStr = saveUpdate(fmt.Sprintf("updates LiquidStake feature from %v to %v", oldHC.Features.LiquidStake, msg.HostChain.Features.LiquidStake))
}
err := oldHC.Features.ValdidateBasic()
err = oldHC.Features.ValdidateBasic()
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -277,6 +278,24 @@ func (k msgServer) DeleteHostChain(goCtx context.Context, msg *types.MsgDeleteHo
return nil, errorsmod.Wrap(sdkerrors.ErrKeyNotFound, "id not set")
}

// check pending packets, do not allow to delete if packets are pending.
portID := types.MustICAPortIDFromOwner(hc.IcaAccount.Owner)
channelID, ok := k.icaControllerKeeper.GetOpenActiveChannel(ctx, hc.ChainId, portID)
if !ok {
return nil, errorsmod.Wrapf(channeltypes.ErrChannelNotFound, "PortID: %s, connectionID: %s", portID, hc.ConnectionId)
}
nextSendSeq, ok := k.ibcKeeper.ChannelKeeper.GetNextSequenceSend(ctx, portID, channelID)
if !ok {
return nil, errorsmod.Wrapf(channeltypes.ErrSequenceSendNotFound, "PortID: %s, channelID: %s", portID, channelID)
}
nextAckSeq, ok := k.ibcKeeper.ChannelKeeper.GetNextSequenceAck(ctx, portID, channelID)
if !ok {
return nil, errorsmod.Wrapf(channeltypes.ErrSequenceAckNotFound, "PortID: %s, channelID: %s", portID, channelID)
}
if nextSendSeq != nextAckSeq {
return nil, errorsmod.Wrapf(channeltypes.ErrPacketSequenceOutOfOrder, "PortID: %s, channelID: %s, NextSendSequence: %v, NextAckSequence: %v", portID, channelID, nextSendSeq, nextAckSeq)
}

k.RemoveHostChain(
ctx,
msg.Id,
Expand Down
Loading

0 comments on commit ba2aa32

Please sign in to comment.