-
Notifications
You must be signed in to change notification settings - Fork 586
/
account.go
130 lines (106 loc) · 6.61 KB
/
account.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package keeper
import (
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cosmos/ibc-go/v7/internal/logging"
icatypes "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/types"
channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types"
host "github.com/cosmos/ibc-go/v7/modules/core/24-host"
)
// RegisterInterchainAccount is the entry point to registering an interchain account:
// - It generates a new port identifier using the provided owner string, binds to the port identifier and claims the associated capability.
// - Callers are expected to provide the appropriate application version string.
// - For example, this could be an ICS27 encoded metadata type or an ICS29 encoded metadata type with a nested application version.
// - A new MsgChannelOpenInit is routed through the MsgServiceRouter, executing the OnOpenChanInit callback stack as configured.
// - 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.
//
// Deprecated: this is a legacy API that is only intended to function correctly in workflows where an underlying authentication application has been set.
// Calling this API will result in all packet callbacks being routed to the underlying application.
// Please use MsgRegisterInterchainAccount for use cases which do not need to route to an underlying application.
// Prior to v6.x.x of ibc-go, the controller module was only functional as middleware, with authentication performed
// by the underlying application. For a full summary of the changes in v6.x.x, please see ADR009.
// This API will be removed in later releases.
func (k Keeper) RegisterInterchainAccount(ctx sdk.Context, connectionID, owner, version string) error {
portID, err := icatypes.NewControllerPortID(owner)
if err != nil {
return err
}
if k.IsMiddlewareDisabled(ctx, portID, connectionID) && !k.IsActiveChannelClosed(ctx, connectionID, portID) {
return sdkerrors.Wrap(icatypes.ErrInvalidChannelFlow, "channel is already active or a handshake is in flight")
}
k.SetMiddlewareEnabled(ctx, portID, connectionID)
_, err = k.registerInterchainAccount(ctx, connectionID, portID, version, channeltypes.UNORDERED)
if err != nil {
return err
}
return nil
}
// RegisterInterchainAccountWithOrdering is the entry point to registering an interchain account:
// - It generates a new port identifier using the provided owner string, binds to the port identifier and claims the associated capability.
// - Callers are expected to provide the appropriate application version string.
// - For example, this could be an ICS27 encoded metadata type or an ICS29 encoded metadata type with a nested application version.
// - A new MsgChannelOpenInit is routed through the MsgServiceRouter, executing the OnOpenChanInit callback stack as configured.
// - 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.
//
// Deprecated: this is a legacy API that is only intended to function correctly in workflows where an underlying authentication application has been set.
// Calling this API will result in all packet callbacks being routed to the underlying application.
// Please use MsgRegisterInterchainAccount for use cases which do not need to route to an underlying application.
// Prior to v6.x.x of ibc-go, the controller module was only functional as middleware, with authentication performed
// by the underlying application. For a full summary of the changes in v6.x.x, please see ADR009.
// This API will be removed in later releases.
func (k Keeper) RegisterInterchainAccountWithOrdering(ctx sdk.Context, connectionID, owner, version string, ordering channeltypes.Order) error {
portID, err := icatypes.NewControllerPortID(owner)
if err != nil {
return err
}
if k.IsMiddlewareDisabled(ctx, portID, connectionID) && !k.IsActiveChannelClosed(ctx, connectionID, portID) {
return sdkerrors.Wrap(icatypes.ErrInvalidChannelFlow, "channel is already active or a handshake is in flight")
}
k.SetMiddlewareEnabled(ctx, portID, connectionID)
// use ORDER_UNORDERED as default in case ordering is NONE
if ordering == channeltypes.NONE {
ordering = channeltypes.UNORDERED
}
_, err = k.registerInterchainAccount(ctx, connectionID, portID, version, ordering)
if err != nil {
return err
}
return nil
}
// 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, portID, version string, ordering channeltypes.Order) (string, error) {
// 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", activeChannelID, portID, connectionID)
}
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)
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)
}
}
msg := channeltypes.NewMsgChannelOpenInit(portID, version, ordering, []string{connectionID}, icatypes.HostPortID, authtypes.NewModuleAddress(icatypes.ModuleName).String())
handler := k.msgRouter.Handler(msg)
res, err := handler(ctx, msg)
if err != nil {
return "", err
}
events := res.GetEvents()
k.Logger(ctx).Debug("emitting interchain account registration events", logging.SdkEventsToLogArguments(events))
// NOTE: The sdk msg handler creates a new EventManager, so events must be correctly propagated back to the current context
ctx.EventManager().EmitEvents(events)
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
}