Some checks failed
CodeQL / Analyze (push) Waiting to run
golangci-lint / lint (push) Waiting to run
Tests / Code Coverage / build (amd64) (push) Waiting to run
Tests / Code Coverage / build (arm64) (push) Waiting to run
Tests / Code Coverage / unit-tests (map[additional-args:-tags="test_e2e" name:e2e path:./e2e]) (push) Waiting to run
Tests / Code Coverage / unit-tests (map[name:08-wasm path:./modules/light-clients/08-wasm]) (push) Waiting to run
Tests / Code Coverage / unit-tests (map[name:ibc-go path:.]) (push) Waiting to run
Docker Build & Push Simapp (main) / docker-build (push) Has been cancelled
121 lines
4.5 KiB
Go
121 lines
4.5 KiB
Go
package keeper
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
errorsmod "cosmossdk.io/errors"
|
|
|
|
sdk "git.cw.tr/mukan-network/mukan-sdk/types"
|
|
|
|
icatypes "git.cw.tr/mukan-network/mukan-ibc/modules/apps/27-interchain-accounts/types"
|
|
channeltypes "git.cw.tr/mukan-network/mukan-ibc/modules/core/04-channel/types"
|
|
)
|
|
|
|
// OnChanOpenTry performs basic validation of the ICA channel
|
|
// and registers a new interchain account (if it doesn't exist).
|
|
// The version returned will include the registered interchain
|
|
// account address.
|
|
func (k Keeper) OnChanOpenTry(
|
|
ctx sdk.Context,
|
|
order channeltypes.Order,
|
|
connectionHops []string,
|
|
portID,
|
|
channelID string,
|
|
counterparty channeltypes.Counterparty,
|
|
counterpartyVersion string,
|
|
) (string, error) {
|
|
if portID != icatypes.HostPortID {
|
|
return "", errorsmod.Wrapf(icatypes.ErrInvalidHostPort, "expected %s, got %s", icatypes.HostPortID, portID)
|
|
}
|
|
|
|
metadata, err := icatypes.MetadataFromVersion(counterpartyVersion)
|
|
if err != nil {
|
|
// Propose the default metadata if the counterparty version is invalid
|
|
connection, err := k.channelKeeper.GetConnection(ctx, connectionHops[0])
|
|
if err != nil {
|
|
return "", errorsmod.Wrapf(err, "failed to retrieve connection %s", connectionHops[0])
|
|
}
|
|
|
|
k.Logger(ctx).Debug("counterparty version is invalid, proposing default metadata")
|
|
metadata = icatypes.NewDefaultMetadata(connection.Counterparty.ConnectionId, connectionHops[0])
|
|
}
|
|
|
|
// set here the HostConnectionId in case the controller did not set it
|
|
metadata.HostConnectionId = connectionHops[0]
|
|
|
|
if err = icatypes.ValidateHostMetadata(ctx, k.channelKeeper, connectionHops, metadata); err != nil {
|
|
return "", err
|
|
}
|
|
|
|
activeChannelID, found := k.GetActiveChannelID(ctx, connectionHops[0], counterparty.PortId)
|
|
if found {
|
|
channel, found := k.channelKeeper.GetChannel(ctx, portID, activeChannelID)
|
|
if !found {
|
|
panic(fmt.Errorf("active channel mapping set for %s but channel does not exist in channel store", activeChannelID))
|
|
}
|
|
|
|
if channel.State != channeltypes.CLOSED {
|
|
return "", errorsmod.Wrapf(icatypes.ErrActiveChannelAlreadySet, "existing active channel %s for portID %s must be %s", activeChannelID, portID, channeltypes.CLOSED)
|
|
}
|
|
|
|
// if a channel is being reopened, we allow the controller to propose new fields
|
|
// which are not exactly the same as the previous. The provided address will
|
|
// be overwritten with the correct one before the metadata is returned.
|
|
}
|
|
|
|
var accAddress sdk.AccAddress
|
|
|
|
interchainAccAddr, found := k.GetInterchainAccountAddress(ctx, metadata.HostConnectionId, counterparty.PortId)
|
|
if found {
|
|
// reopening an interchain account
|
|
k.Logger(ctx).Info("reopening existing interchain account", "address", interchainAccAddr)
|
|
accAddress = sdk.MustAccAddressFromBech32(interchainAccAddr)
|
|
if _, ok := k.accountKeeper.GetAccount(ctx, accAddress).(*icatypes.InterchainAccount); !ok {
|
|
return "", errorsmod.Wrapf(icatypes.ErrInvalidAccountReopening, "existing account address %s, does not have interchain account type", accAddress)
|
|
}
|
|
|
|
} else {
|
|
accAddress, err = k.createInterchainAccount(ctx, metadata.HostConnectionId, counterparty.PortId)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
k.Logger(ctx).Info("successfully created new interchain account", "host-connection-id", metadata.HostConnectionId, "port-id", counterparty.PortId, "address", accAddress)
|
|
}
|
|
|
|
metadata.Address = accAddress.String()
|
|
versionBytes, err := icatypes.ModuleCdc.MarshalJSON(&metadata)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return string(versionBytes), nil
|
|
}
|
|
|
|
// OnChanOpenConfirm completes the handshake process by setting the active channel in state on the host chain
|
|
func (k Keeper) OnChanOpenConfirm(
|
|
ctx sdk.Context,
|
|
portID,
|
|
channelID string,
|
|
) error {
|
|
channel, found := k.channelKeeper.GetChannel(ctx, portID, channelID)
|
|
if !found {
|
|
return errorsmod.Wrapf(channeltypes.ErrChannelNotFound, "failed to retrieve channel %s on port %s", channelID, portID)
|
|
}
|
|
|
|
// It is assumed the controller chain will not allow multiple active channels to be created for the same connectionID/portID
|
|
// If the controller chain does allow multiple active channels to be created for the same connectionID/portID,
|
|
// disallowing overwriting the current active channel guarantees the channel can no longer be used as the controller
|
|
// and host will disagree on what the currently active channel is
|
|
k.SetActiveChannelID(ctx, channel.ConnectionHops[0], channel.Counterparty.PortId, channelID)
|
|
|
|
return nil
|
|
}
|
|
|
|
// OnChanCloseConfirm removes the active channel stored in state
|
|
func (Keeper) OnChanCloseConfirm(
|
|
ctx sdk.Context,
|
|
portID,
|
|
channelID string,
|
|
) error {
|
|
return nil
|
|
}
|