github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/ibc-go/modules/apps/27-interchain-accounts/host/keeper/handshake.go (about) 1 package keeper 2 3 import ( 4 "fmt" 5 "strings" 6 7 sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types" 8 sdkerrors "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types/errors" 9 capabilitytypes "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/capability/types" 10 icatypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/apps/27-interchain-accounts/types" 11 channeltypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/04-channel/types" 12 host "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/24-host" 13 ) 14 15 // OnChanOpenTry performs basic validation of the ICA channel 16 // and registers a new interchain account (if it doesn't exist). 17 // The version returned will include the registered interchain 18 // account address. 19 func (k Keeper) OnChanOpenTry( 20 ctx sdk.Context, 21 order channeltypes.Order, 22 connectionHops []string, 23 portID, 24 channelID string, 25 chanCap *capabilitytypes.Capability, 26 counterparty channeltypes.Counterparty, 27 counterpartyVersion string, 28 ) (string, error) { 29 if order != channeltypes.ORDERED { 30 return "", sdkerrors.Wrapf(channeltypes.ErrInvalidChannelOrdering, "expected %s channel, got %s", channeltypes.ORDERED, order) 31 } 32 33 if portID != icatypes.PortID { 34 return "", sdkerrors.Wrapf(icatypes.ErrInvalidHostPort, "expected %s, got %s", icatypes.PortID, portID) 35 } 36 37 if !strings.HasPrefix(counterparty.PortId, icatypes.PortPrefix) { 38 return "", sdkerrors.Wrapf(icatypes.ErrInvalidControllerPort, "expected %s{owner-account-address}, got %s", icatypes.PortPrefix, counterparty.PortId) 39 } 40 41 var metadata icatypes.Metadata 42 if err := icatypes.ModuleCdc.UnmarshalJSON([]byte(counterpartyVersion), &metadata); err != nil { 43 return "", sdkerrors.Wrapf(icatypes.ErrUnknownDataType, "cannot unmarshal ICS-27 interchain accounts metadata") 44 } 45 46 if err := icatypes.ValidateHostMetadata(ctx, k.channelKeeper, connectionHops, metadata); err != nil { 47 return "", err 48 } 49 50 activeChannelID, found := k.GetActiveChannelID(ctx, connectionHops[0], counterparty.PortId) 51 if found { 52 channel, found := k.channelKeeper.GetChannel(ctx, portID, activeChannelID) 53 if !found { 54 panic(fmt.Sprintf("active channel mapping set for %s but channel does not exist in channel store", activeChannelID)) 55 } 56 57 if channel.State == channeltypes.OPEN { 58 return "", sdkerrors.Wrapf(icatypes.ErrActiveChannelAlreadySet, "existing active channel %s for portID %s is already OPEN", activeChannelID, portID) 59 } 60 61 if !icatypes.IsPreviousMetadataEqual(channel.Version, metadata) { 62 return "", sdkerrors.Wrap(icatypes.ErrInvalidVersion, "previous active channel metadata does not match provided version") 63 } 64 } 65 66 // On the host chain the capability may only be claimed during the OnChanOpenTry 67 // The capability being claimed in OpenInit is for a controller chain (the port is different) 68 if err := k.ClaimCapability(ctx, chanCap, host.ChannelCapabilityPath(portID, channelID)); err != nil { 69 return "", sdkerrors.Wrapf(err, "failed to claim capability for channel %s on port %s", channelID, portID) 70 } 71 72 accAddress := icatypes.GenerateAddress(k.accountKeeper.GetModuleAddress(icatypes.ModuleName), metadata.HostConnectionId, counterparty.PortId) 73 74 // Register interchain account if it does not already exist 75 k.RegisterInterchainAccount(ctx, metadata.HostConnectionId, counterparty.PortId, accAddress) 76 77 metadata.Address = accAddress.String() 78 versionBytes, err := icatypes.ModuleCdc.MarshalJSON(&metadata) 79 if err != nil { 80 return "", err 81 } 82 83 return string(versionBytes), nil 84 } 85 86 // OnChanOpenConfirm completes the handshake process by setting the active channel in state on the host chain 87 func (k Keeper) OnChanOpenConfirm( 88 ctx sdk.Context, 89 portID, 90 channelID string, 91 ) error { 92 channel, found := k.channelKeeper.GetChannel(ctx, portID, channelID) 93 if !found { 94 return sdkerrors.Wrapf(channeltypes.ErrChannelNotFound, "failed to retrieve channel %s on port %s", channelID, portID) 95 } 96 97 // It is assumed the controller chain will not allow multiple active channels to be created for the same connectionID/portID 98 // If the controller chain does allow multiple active channels to be created for the same connectionID/portID, 99 // disallowing overwriting the current active channel guarantees the channel can no longer be used as the controller 100 // and host will disagree on what the currently active channel is 101 k.SetActiveChannelID(ctx, channel.ConnectionHops[0], channel.Counterparty.PortId, channelID) 102 103 return nil 104 } 105 106 // OnChanCloseConfirm removes the active channel stored in state 107 func (k Keeper) OnChanCloseConfirm( 108 ctx sdk.Context, 109 portID, 110 channelID string, 111 ) error { 112 return nil 113 }