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  }