github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/ibc-go/modules/apps/27-interchain-accounts/controller/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 ) 13 14 // OnChanOpenInit performs basic validation of channel initialization. 15 // The channel order must be ORDERED, the counterparty port identifier 16 // must be the host chain representation as defined in the types package, 17 // the channel version must be equal to the version in the types package, 18 // there must not be an active channel for the specfied port identifier, 19 // and the interchain accounts module must be able to claim the channel 20 // capability. 21 func (k Keeper) OnChanOpenInit( 22 ctx sdk.Context, 23 order channeltypes.Order, 24 connectionHops []string, 25 portID string, 26 channelID string, 27 chanCap *capabilitytypes.Capability, 28 counterparty channeltypes.Counterparty, 29 version string, 30 ) (string, error) { 31 if order != channeltypes.ORDERED { 32 return "", sdkerrors.Wrapf(channeltypes.ErrInvalidChannelOrdering, "expected %s channel, got %s", channeltypes.ORDERED, order) 33 } 34 35 if !strings.HasPrefix(portID, icatypes.PortPrefix) { 36 return "", sdkerrors.Wrapf(icatypes.ErrInvalidControllerPort, "expected %s{owner-account-address}, got %s", icatypes.PortPrefix, portID) 37 } 38 39 if counterparty.PortId != icatypes.PortID { 40 return "", sdkerrors.Wrapf(icatypes.ErrInvalidHostPort, "expected %s, got %s", icatypes.PortID, counterparty.PortId) 41 } 42 43 var metadata icatypes.Metadata 44 if strings.TrimSpace(version) == "" { 45 connection, err := k.channelKeeper.GetConnection(ctx, connectionHops[0]) 46 if err != nil { 47 return "", err 48 } 49 50 metadata = icatypes.NewDefaultMetadata(connectionHops[0], connection.GetCounterparty().GetConnectionID()) 51 } else { 52 if err := icatypes.ModuleCdc.UnmarshalJSON([]byte(version), &metadata); err != nil { 53 return "", sdkerrors.Wrapf(icatypes.ErrUnknownDataType, "cannot unmarshal ICS-27 interchain accounts metadata") 54 } 55 } 56 57 if err := icatypes.ValidateControllerMetadata(ctx, k.channelKeeper, connectionHops, metadata); err != nil { 58 return "", err 59 } 60 61 activeChannelID, found := k.GetActiveChannelID(ctx, connectionHops[0], portID) 62 if found { 63 channel, found := k.channelKeeper.GetChannel(ctx, portID, activeChannelID) 64 if !found { 65 panic(fmt.Sprintf("active channel mapping set for %s but channel does not exist in channel store", activeChannelID)) 66 } 67 68 if channel.State == channeltypes.OPEN { 69 return "", sdkerrors.Wrapf(icatypes.ErrActiveChannelAlreadySet, "existing active channel %s for portID %s is already OPEN", activeChannelID, portID) 70 } 71 72 if !icatypes.IsPreviousMetadataEqual(channel.Version, metadata) { 73 return "", sdkerrors.Wrap(icatypes.ErrInvalidVersion, "previous active channel metadata does not match provided version") 74 } 75 } 76 77 return string(icatypes.ModuleCdc.MustMarshalJSON(&metadata)), nil 78 } 79 80 // OnChanOpenAck sets the active channel for the interchain account/owner pair 81 // and stores the associated interchain account address in state keyed by it's corresponding port identifier 82 func (k Keeper) OnChanOpenAck( 83 ctx sdk.Context, 84 portID, 85 channelID string, 86 counterpartyVersion string, 87 ) error { 88 if portID == icatypes.PortID { 89 return sdkerrors.Wrapf(icatypes.ErrInvalidControllerPort, "portID cannot be host chain port ID: %s", icatypes.PortID) 90 } 91 92 if !strings.HasPrefix(portID, icatypes.PortPrefix) { 93 return sdkerrors.Wrapf(icatypes.ErrInvalidControllerPort, "expected %s{owner-account-address}, got %s", icatypes.PortPrefix, portID) 94 } 95 96 var metadata icatypes.Metadata 97 if err := icatypes.ModuleCdc.UnmarshalJSON([]byte(counterpartyVersion), &metadata); err != nil { 98 return sdkerrors.Wrapf(icatypes.ErrUnknownDataType, "cannot unmarshal ICS-27 interchain accounts metadata") 99 } 100 101 if activeChannelID, found := k.GetOpenActiveChannel(ctx, metadata.ControllerConnectionId, portID); found { 102 return sdkerrors.Wrapf(icatypes.ErrActiveChannelAlreadySet, "existing active channel %s for portID %s", activeChannelID, portID) 103 } 104 105 channel, found := k.channelKeeper.GetChannel(ctx, portID, channelID) 106 if !found { 107 return sdkerrors.Wrapf(channeltypes.ErrChannelNotFound, "failed to retrieve channel %s on port %s", channelID, portID) 108 } 109 110 if err := icatypes.ValidateControllerMetadata(ctx, k.channelKeeper, channel.ConnectionHops, metadata); err != nil { 111 return err 112 } 113 114 if strings.TrimSpace(metadata.Address) == "" { 115 return sdkerrors.Wrap(icatypes.ErrInvalidAccountAddress, "interchain account address cannot be empty") 116 } 117 118 k.SetActiveChannelID(ctx, metadata.ControllerConnectionId, portID, channelID) 119 k.SetInterchainAccountAddress(ctx, metadata.ControllerConnectionId, portID, metadata.Address) 120 121 return nil 122 } 123 124 // OnChanCloseConfirm removes the active channel stored in state 125 func (k Keeper) OnChanCloseConfirm( 126 ctx sdk.Context, 127 portID, 128 channelID string, 129 ) error { 130 return nil 131 }