Skip to content

Commit

Permalink
feat: implementing SubmitTx gRPC endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
seantking committed Aug 30, 2022
1 parent f263794 commit 09c053a
Show file tree
Hide file tree
Showing 2 changed files with 151 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@ import (
"context"

sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"

"github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts/controller/types"
icatypes "github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts/types"
channeltypes "github.com/cosmos/ibc-go/v5/modules/core/04-channel/types"
host "github.com/cosmos/ibc-go/v5/modules/core/24-host"
)

var _ types.MsgServer = Keeper{}
Expand All @@ -26,5 +30,27 @@ func (k Keeper) RegisterAccount(goCtx context.Context, msg *types.MsgRegisterAcc

// SubmitTx defines a rpc handler for MsgSubmitTx
func (k Keeper) SubmitTx(goCtx context.Context, msg *types.MsgSubmitTx) (*types.MsgSubmitTxResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)

portID, err := icatypes.NewControllerPortID(msg.Owner)
if err != nil {
return nil, err
}

channelID, found := k.GetActiveChannelID(ctx, msg.ConnectionId, portID)
if !found {
return nil, sdkerrors.Wrapf(icatypes.ErrActiveChannelNotFound, "failed to retrieve active channel for port %s", portID)
}

chanCap, found := k.scopedKeeper.GetCapability(ctx, host.ChannelCapabilityPath(portID, channelID))
if !found {
return nil, sdkerrors.Wrap(channeltypes.ErrChannelCapabilityNotFound, "module does not own channel capability")
}

_, err = k.SendTx(ctx, chanCap, msg.ConnectionId, portID, msg.PacketData, msg.TimeoutTimestamp)
if err != nil {
return nil, err
}

return &types.MsgSubmitTxResponse{}, nil
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
package keeper_test

import (
"time"

sdk "github.com/cosmos/cosmos-sdk/types"
sdktypes "github.com/cosmos/cosmos-sdk/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"

icatypes "github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts/controller/types"
"github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts/controller/types"
icacontrollertypes "github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts/controller/types"
icatypes "github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts/types"
clienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
channeltypes "github.com/cosmos/ibc-go/v5/modules/core/04-channel/types"
host "github.com/cosmos/ibc-go/v5/modules/core/24-host"
ibctesting "github.com/cosmos/ibc-go/v5/testing"
)

func (suite *KeeperTestSuite) TestRegisterAccount() {
var (
msg *icatypes.MsgRegisterAccount
msg *icacontrollertypes.MsgRegisterAccount
expectedChannelID = "channel-0"
)

Expand Down Expand Up @@ -63,7 +70,7 @@ func (suite *KeeperTestSuite) TestRegisterAccount() {
path := NewICAPath(suite.chainA, suite.chainB)
suite.coordinator.SetupConnections(path)

msg = icatypes.NewMsgRegisterAccount(ibctesting.FirstConnectionID, ibctesting.TestAccAddress, "")
msg = icacontrollertypes.NewMsgRegisterAccount(ibctesting.FirstConnectionID, ibctesting.TestAccAddress, "")

tc.malleate()

Expand All @@ -85,3 +92,118 @@ func (suite *KeeperTestSuite) TestRegisterAccount() {
}
}
}

func (suite *KeeperTestSuite) TestSubmitTx() {
var (
path *ibctesting.Path
owner string
connectionId string
icaMsg sdk.Msg
)

testCases := []struct {
name string
malleate func()
expPass bool
}{
{
"success", func() {
owner = TestOwnerAddress
connectionId = path.EndpointA.ConnectionID
},
true,
},
/*
{
"failure - owner address is empty", func() {
owner = ""
connectionId = path.EndpointA.ConnectionID
},
},
{
"failure - active channel does not exist for connection ID", func() {
owner = TestOwnerAddress
connectionId = "connection-100"
},
},
{
"failure - active channel does not exist for port ID", func() {
owner = "cosmos153lf4zntqt33a4v0sm5cytrxyqn78q7kz8j8x5"
connectionId = path.EndpointA.ConnectionID
},
},
{
"failure - module does not own channel capability", func() {
owner = TestOwnerAddress
connectionId = path.EndpointA.ConnectionID
icaMsg = &banktypes.MsgSend{
FromAddress: "source-address",
ToAddress: "destination-address",
Amount: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100))),
}
},
},
*/
}

for _, tc := range testCases {
tc := tc

suite.Run(tc.name, func() {
suite.SetupTest()

path = NewICAPath(suite.chainA, suite.chainB)
suite.coordinator.SetupConnections(path)

tc.malleate() // malleate mutates test data

err := SetupICAPath(path, TestOwnerAddress)
suite.Require().NoError(err)

portID, err := icatypes.NewControllerPortID(TestOwnerAddress)
suite.Require().NoError(err)

// Get the address of the interchain account stored in state during handshake step
interchainAccountAddr, found := suite.chainA.GetSimApp().ICAControllerKeeper.GetInterchainAccountAddress(suite.chainA.GetContext(), path.EndpointA.ConnectionID, portID)
suite.Require().True(found)

icaAddr, err := sdk.AccAddressFromBech32(interchainAccountAddr)
suite.Require().NoError(err)

// Check if account is created
interchainAccount := suite.chainB.GetSimApp().AccountKeeper.GetAccount(suite.chainB.GetContext(), icaAddr)
suite.Require().Equal(interchainAccount.GetAddress().String(), interchainAccountAddr)

// Create bank transfer message to execute on the host
icaMsg = &banktypes.MsgSend{
FromAddress: interchainAccountAddr,
ToAddress: suite.chainB.SenderAccount.GetAddress().String(),
Amount: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100))),
}

data, err := icatypes.SerializeCosmosTx(suite.chainA.Codec, []sdk.Msg{icaMsg})
suite.Require().NoError(err)

packetData := icatypes.InterchainAccountPacketData{
Type: icatypes.EXECUTE_TX,
Data: data,
Memo: "memo",
}

// timeoutTimestamp set to max value with the unsigned bit shifted to sastisfy hermes timestamp conversion
// it is the responsibility of the auth module developer to ensure an appropriate timeout timestamp
timeoutTimestamp := suite.chainA.GetContext().BlockTime().Add(time.Minute).UnixNano()

msg := types.NewMsgSubmitTx(owner, connectionId, clienttypes.NewHeight(0, 0), uint64(timeoutTimestamp), packetData)
res, err := suite.chainA.GetSimApp().ICAControllerKeeper.SubmitTx(sdk.WrapSDKContext(suite.chainA.GetContext()), msg)

if tc.expPass {
suite.Require().NoError(err)
suite.Require().NotNil(res)
} else {
suite.Require().Error(err)
suite.Require().Nil(res)
}
})
}
}

0 comments on commit 09c053a

Please sign in to comment.