Skip to content

Commit

Permalink
Implement the rpc handler method for RegisterAccount (#2110)
Browse files Browse the repository at this point in the history
  • Loading branch information
chatton authored Aug 29, 2022
1 parent dcd616c commit b7d8359
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 8 deletions.
26 changes: 19 additions & 7 deletions modules/apps/27-interchain-accounts/controller/keeper/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,37 +17,49 @@ import (
// - An error is returned if the port identifier is already in use. Gaining access to interchain accounts whose channels
// have closed cannot be done with this function. A regular MsgChannelOpenInit must be used.
func (k Keeper) RegisterInterchainAccount(ctx sdk.Context, connectionID, owner, version string) error {
_, err := k.registerInterchainAccount(ctx, connectionID, owner, version)
return err
}

// registerInterchainAccount registers an interchain account, returning the channel id of the MsgChannelOpenInitResponse
// and an error if one occurred.
func (k Keeper) registerInterchainAccount(ctx sdk.Context, connectionID, owner, version string) (string, error) {
portID, err := icatypes.NewControllerPortID(owner)
if err != nil {
return err
return "", err
}

// if there is an active channel for this portID / connectionID return an error
activeChannelID, found := k.GetOpenActiveChannel(ctx, connectionID, portID)
if found {
return sdkerrors.Wrapf(icatypes.ErrActiveChannelAlreadySet, "existing active channel %s for portID %s on connection %s for owner %s", activeChannelID, portID, connectionID, owner)
return "", sdkerrors.Wrapf(icatypes.ErrActiveChannelAlreadySet, "existing active channel %s for portID %s on connection %s for owner %s", activeChannelID, portID, connectionID, owner)
}

switch {
case k.portKeeper.IsBound(ctx, portID) && !k.IsBound(ctx, portID):
return sdkerrors.Wrapf(icatypes.ErrPortAlreadyBound, "another module has claimed capability for and bound port with portID: %s", portID)
return "", sdkerrors.Wrapf(icatypes.ErrPortAlreadyBound, "another module has claimed capability for and bound port with portID: %s", portID)
case !k.portKeeper.IsBound(ctx, portID):
cap := k.BindPort(ctx, portID)
if err := k.ClaimCapability(ctx, cap, host.PortPath(portID)); err != nil {
return sdkerrors.Wrapf(err, "unable to bind to newly generated portID: %s", portID)
return "", sdkerrors.Wrapf(err, "unable to bind to newly generated portID: %s", portID)
}
}

msg := channeltypes.NewMsgChannelOpenInit(portID, version, channeltypes.ORDERED, []string{connectionID}, icatypes.PortID, icatypes.ModuleName)
handler := k.msgRouter.Handler(msg)

res, err := handler(ctx, msg)
if err != nil {
return err
return "", err
}

// NOTE: The sdk msg handler creates a new EventManager, so events must be correctly propagated back to the current context
ctx.EventManager().EmitEvents(res.GetEvents())

return nil
firstMsgResponse := res.MsgResponses[0]
channelOpenInitResponse, ok := firstMsgResponse.GetCachedValue().(*channeltypes.MsgChannelOpenInitResponse)
if !ok {
return "", sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "failed to covert %T message response to %T", firstMsgResponse.GetCachedValue(), &channeltypes.MsgChannelOpenInitResponse{})
}

return channelOpenInitResponse.ChannelId, nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,23 @@ package keeper
import (
"context"

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

"github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts/controller/types"
)

var _ types.MsgServer = Keeper{}

// RegisterAccount defines a rpc handler for MsgRegisterAccount
func (k Keeper) RegisterAccount(goCtx context.Context, msg *types.MsgRegisterAccount) (*types.MsgRegisterAccountResponse, error) {
return &types.MsgRegisterAccountResponse{}, nil
ctx := sdk.UnwrapSDKContext(goCtx)

channelID, err := k.registerInterchainAccount(ctx, msg.ConnectionId, msg.Owner, msg.Version)
if err != nil {
return nil, err
}

return &types.MsgRegisterAccountResponse{
ChannelId: channelID,
}, nil
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package keeper_test

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

icatypes "github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts/controller/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
expectedChannelID = "channel-0"
)

testCases := []struct {
name string
expPass bool
malleate func()
}{
{
"success",
true,
func() {},
},
{
"invalid connection id",
false,
func() {
msg.ConnectionId = "connection-100"
},
},
{
"non-empty owner address is valid",
true,
func() {
msg.Owner = "<invalid-owner>"
},
},
{
"empty address invalid",
false,
func() {
msg.Owner = ""
},
},
{
"port is already bound for owner but capability is claimed by another module",
false,
func() {
capability := suite.chainA.GetSimApp().IBCKeeper.PortKeeper.BindPort(suite.chainA.GetContext(), TestPortID)
err := suite.chainA.GetSimApp().TransferKeeper.ClaimCapability(suite.chainA.GetContext(), capability, host.PortPath(TestPortID))
suite.Require().NoError(err)
},
},
}

for _, tc := range testCases {
suite.SetupTest()

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

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

tc.malleate()

ctx := suite.chainA.GetContext()
res, err := suite.chainA.GetSimApp().ICAControllerKeeper.RegisterAccount(ctx, msg)

if tc.expPass {
suite.Require().NoError(err)
suite.Require().NotNil(res)
suite.Require().Equal(expectedChannelID, res.ChannelId)

events := ctx.EventManager().Events()
suite.Require().Len(events, 2)
suite.Require().Equal(events[0].Type, channeltypes.EventTypeChannelOpenInit)
suite.Require().Equal(events[1].Type, sdktypes.EventTypeMessage)
} else {
suite.Require().Error(err)
suite.Require().Nil(res)
}
}
}

0 comments on commit b7d8359

Please sign in to comment.