github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/ibc-go/modules/apps/27-interchain-accounts/host/keeper/keeper.go (about)

     1  package keeper
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/fibonacci-chain/fbc/libs/tendermint/libs/log"
     8  
     9  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/baseapp"
    10  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/codec"
    11  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
    12  	capabilitykeeper "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/capability/keeper"
    13  	capabilitytypes "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/capability/types"
    14  	"github.com/fibonacci-chain/fbc/libs/ibc-go/modules/apps/27-interchain-accounts/host/types"
    15  	icatypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/apps/27-interchain-accounts/types"
    16  	channeltypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/04-channel/types"
    17  	host "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/24-host"
    18  	paramtypes "github.com/fibonacci-chain/fbc/x/params"
    19  )
    20  
    21  // Keeper defines the IBC interchain accounts host keeper
    22  type Keeper struct {
    23  	storeKey   sdk.StoreKey
    24  	cdc        *codec.CodecProxy
    25  	paramSpace paramtypes.Subspace
    26  
    27  	channelKeeper icatypes.ChannelKeeper
    28  	portKeeper    icatypes.PortKeeper
    29  	accountKeeper icatypes.AccountKeeper
    30  
    31  	scopedKeeper capabilitykeeper.ScopedKeeper
    32  
    33  	msgRouter *baseapp.MsgServiceRouter
    34  }
    35  
    36  // NewKeeper creates a new interchain accounts host Keeper instance
    37  func NewKeeper(
    38  	cdc *codec.CodecProxy, key sdk.StoreKey, paramSpace paramtypes.Subspace,
    39  	channelKeeper icatypes.ChannelKeeper, portKeeper icatypes.PortKeeper,
    40  	accountKeeper icatypes.AccountKeeper, scopedKeeper capabilitykeeper.ScopedKeeper, msgRouter *baseapp.MsgServiceRouter,
    41  ) Keeper {
    42  	// ensure ibc interchain accounts module account is set
    43  	if addr := accountKeeper.GetModuleAddress(icatypes.ModuleName); addr == nil {
    44  		panic("the Interchain Accounts module account has not been set")
    45  	}
    46  
    47  	// set KeyTable if it has not already been set
    48  	if !paramSpace.HasKeyTable() {
    49  		paramSpace = paramSpace.WithKeyTable(types.ParamKeyTable())
    50  	}
    51  
    52  	return Keeper{
    53  		storeKey:      key,
    54  		cdc:           cdc,
    55  		paramSpace:    paramSpace,
    56  		channelKeeper: channelKeeper,
    57  		portKeeper:    portKeeper,
    58  		accountKeeper: accountKeeper,
    59  		scopedKeeper:  scopedKeeper,
    60  		msgRouter:     msgRouter,
    61  	}
    62  }
    63  
    64  // Logger returns the application logger, scoped to the associated module
    65  func (k Keeper) Logger(ctx sdk.Context) log.Logger {
    66  	return ctx.Logger().With("module", fmt.Sprintf("x/%s-%s", host.ModuleName, icatypes.ModuleName))
    67  }
    68  
    69  // BindPort stores the provided portID and binds to it, returning the associated capability
    70  func (k Keeper) BindPort(ctx sdk.Context, portID string) *capabilitytypes.Capability {
    71  	store := ctx.KVStore(k.storeKey)
    72  	store.Set(icatypes.KeyPort(portID), []byte{0x01})
    73  
    74  	return k.portKeeper.BindPort(ctx, portID)
    75  }
    76  
    77  // IsBound checks if the interchain account host module is already bound to the desired port
    78  func (k Keeper) IsBound(ctx sdk.Context, portID string) bool {
    79  	_, ok := k.scopedKeeper.GetCapability(ctx, host.PortPath(portID))
    80  	return ok
    81  }
    82  
    83  // AuthenticateCapability wraps the scopedKeeper's AuthenticateCapability function
    84  func (k Keeper) AuthenticateCapability(ctx sdk.Context, cap *capabilitytypes.Capability, name string) bool {
    85  	return k.scopedKeeper.AuthenticateCapability(ctx, cap, name)
    86  }
    87  
    88  // ClaimCapability wraps the scopedKeeper's ClaimCapability function
    89  func (k Keeper) ClaimCapability(ctx sdk.Context, cap *capabilitytypes.Capability, name string) error {
    90  	return k.scopedKeeper.ClaimCapability(ctx, cap, name)
    91  }
    92  
    93  // GetActiveChannelID retrieves the active channelID from the store keyed by the provided connectionID and portID
    94  func (k Keeper) GetActiveChannelID(ctx sdk.Context, connectionID, portID string) (string, bool) {
    95  	store := ctx.KVStore(k.storeKey)
    96  	key := icatypes.KeyActiveChannel(portID, connectionID)
    97  
    98  	if !store.Has(key) {
    99  		return "", false
   100  	}
   101  
   102  	return string(store.Get(key)), true
   103  }
   104  
   105  // GetOpenActiveChannel retrieves the active channelID from the store, keyed by the provided connectionID and portID & checks if the channel in question is in state OPEN
   106  func (k Keeper) GetOpenActiveChannel(ctx sdk.Context, connectionID, portID string) (string, bool) {
   107  	channelID, found := k.GetActiveChannelID(ctx, connectionID, portID)
   108  	if !found {
   109  		return "", false
   110  	}
   111  
   112  	channel, found := k.channelKeeper.GetChannel(ctx, portID, channelID)
   113  
   114  	if found && channel.State == channeltypes.OPEN {
   115  		return channelID, true
   116  	}
   117  
   118  	return "", false
   119  }
   120  
   121  // GetAllActiveChannels returns a list of all active interchain accounts host channels and their associated connection and port identifiers
   122  func (k Keeper) GetAllActiveChannels(ctx sdk.Context) []icatypes.ActiveChannel {
   123  	store := ctx.KVStore(k.storeKey)
   124  	iterator := sdk.KVStorePrefixIterator(store, []byte(icatypes.ActiveChannelKeyPrefix))
   125  	defer iterator.Close()
   126  
   127  	var activeChannels []icatypes.ActiveChannel
   128  	for ; iterator.Valid(); iterator.Next() {
   129  		keySplit := strings.Split(string(iterator.Key()), "/")
   130  
   131  		ch := icatypes.ActiveChannel{
   132  			ConnectionId: keySplit[2],
   133  			PortId:       keySplit[1],
   134  			ChannelId:    string(iterator.Value()),
   135  		}
   136  
   137  		activeChannels = append(activeChannels, ch)
   138  	}
   139  
   140  	return activeChannels
   141  }
   142  
   143  // SetActiveChannelID stores the active channelID, keyed by the provided connectionID and portID
   144  func (k Keeper) SetActiveChannelID(ctx sdk.Context, connectionID, portID, channelID string) {
   145  	store := ctx.KVStore(k.storeKey)
   146  	store.Set(icatypes.KeyActiveChannel(portID, connectionID), []byte(channelID))
   147  }
   148  
   149  // IsActiveChannel returns true if there exists an active channel for the provided connectionID and portID, otherwise false
   150  func (k Keeper) IsActiveChannel(ctx sdk.Context, connectionID, portID string) bool {
   151  	_, ok := k.GetActiveChannelID(ctx, connectionID, portID)
   152  	return ok
   153  }
   154  
   155  // GetInterchainAccountAddress retrieves the InterchainAccount address from the store associated with the provided connectionID and portID
   156  func (k Keeper) GetInterchainAccountAddress(ctx sdk.Context, connectionID, portID string) (string, bool) {
   157  	store := ctx.KVStore(k.storeKey)
   158  	key := icatypes.KeyOwnerAccount(portID, connectionID)
   159  
   160  	if !store.Has(key) {
   161  		return "", false
   162  	}
   163  
   164  	return string(store.Get(key)), true
   165  }
   166  
   167  // GetAllInterchainAccounts returns a list of all registered interchain account addresses and their associated connection and controller port identifiers
   168  func (k Keeper) GetAllInterchainAccounts(ctx sdk.Context) []icatypes.RegisteredInterchainAccount {
   169  	store := ctx.KVStore(k.storeKey)
   170  	iterator := sdk.KVStorePrefixIterator(store, []byte(icatypes.OwnerKeyPrefix))
   171  
   172  	var interchainAccounts []icatypes.RegisteredInterchainAccount
   173  	for ; iterator.Valid(); iterator.Next() {
   174  		keySplit := strings.Split(string(iterator.Key()), "/")
   175  
   176  		acc := icatypes.RegisteredInterchainAccount{
   177  			ConnectionId:   keySplit[2],
   178  			PortId:         keySplit[1],
   179  			AccountAddress: string(iterator.Value()),
   180  		}
   181  
   182  		interchainAccounts = append(interchainAccounts, acc)
   183  	}
   184  
   185  	return interchainAccounts
   186  }
   187  
   188  // SetInterchainAccountAddress stores the InterchainAccount address, keyed by the associated connectionID and portID
   189  func (k Keeper) SetInterchainAccountAddress(ctx sdk.Context, connectionID, portID, address string) {
   190  	store := ctx.KVStore(k.storeKey)
   191  	store.Set(icatypes.KeyOwnerAccount(portID, connectionID), []byte(address))
   192  }