# Interchain Accounts
Interchain accounts (ICAs) allow you to control an account on a host chain from a controller chain.
In this section, you will learn more about:
- Hosting chains and controller chains
- ICA module code
- The authentication module
Another application module implemented in the IBC-Go (opens new window) repository is interchain accounts (ICS-27) (opens new window).
Host Chain: the chain where the interchain account is registered. The host chain listens for IBC packets from a controller chain which should contain instructions (e.g. cosmos SDK messages) which the interchain account will execute.
Controller Chain: the chain that registers and controls an account on a host chain. The controller chain sends IBC packets to the host chain to control the account. A controller chain must have at least one interchain accounts authentication module in order to act as a controller chain.
The interchain accounts application module is structured to support the ability of exclusively enabling controller or host functionality. This can be achieved by simply omitting either controller or host Keeper
from the interchain accounts NewAppModule
constructor function, and mounting only the desired submodule via the IBCRouter
. Alternatively, submodules can be enabled and disabled dynamically using on-chain parameters.
Authentication Module: a custom IBC application module on the controller chain that uses the interchain accounts module API to build custom logic for the creation and management of interchain accounts. An authentication module is required for a controller chain to utilize the interchain accounts module functionality.
Interchain account (ICA): an account on a host chain. An interchain account has all the capabilities of a normal account. However, rather than signing transactions with a private key, a controller chain's authentication module will send IBC packets to the host chain which signal what transactions the interchain account should execute.
The ICA module provides an API for registering an account and for sending interchain transactions. A developer will use this module by implementing an ICA Auth Module (authentication module) and can expose gRPC endpoints for an application or user. Regular accounts use a private key to sign transactions on-chain. interchain accounts are instead controlled programmatically by separate chains via IBC transactions. interchain accounts are implemented as sub-accounts of the interchain accounts module account.
First, look how an account is registered:
To register an account on the host chain, the function RegisterInterchainAccount
(opens new window) is called on the controller chain:
The portID
will be the address of the interchain account Owner prefixed by the default port prefix of the interchain accounts controller submodule icacontroller-
. The ICA module assumes that there is already an IBC connection established between the host and controller chains. As part of RegisterInterchainAccount
, it will open an ORDERED
channel.
The ICA module uses ORDERED
channels to maintain the order of transactions when sending packets from a controller chain to a host chain. A limitation when using ORDERED
channels is that when a packet times out the channel will be closed. In the case of a channel closing, a controller chain needs to be able to regain access to the interchain account registered on this channel.
ICAs offer active channels to create a new channel using the same controller prefixed chain portID
. This means that when an interchain account is registered using the RegisterInterchainAccount
API, a new channel is created on a particular port. During the OnChanOpenAck
and OnChanOpenConfirm
steps (controller & host chain), the Active Channel
for this interchain account is stored in state.
Using the Active Channel
stored in state, it is then possible to create a new channel using the same controller chain portID even if the previously set Active Channel
is in a CLOSED
state.
If the message gets to the host chain (with the NewMsgChannelOpenInit
call shown previously), the ICA module on the host chain also calls RegisterInterchainAccount
(opens new window):
This call goes through the OnChanOpenTry
implementation in the handshake.go
(opens new window) on the host chain:
As a result, a fresh interchain account is created on the host chain. You can find the implementations of OnChanOpenInit
and OnChanOpenAck
in the handshake.go
(opens new window):
There is a one-to-one mapping between an interchain account and a channel to fulfill the requirements for the Active Channels.
In the OnChanOpenAck
you can see that the channel ID and account address will be set in the state:
After registration, the registered account can be used to sign transactions on the host chain:
You can find SendTx
in the relay.go
(opens new window):
This validates the source and destination IDs and uses createOutgoingPacket
to send a transaction, which calls SendPacket
of the IBC core module.
On the host chain, if a packet arrives, OnRecvPacket
in the relay.go
(opens new window) is called:
This calls executeTx
to apply the received transaction on the host chain:
authenticateTx
ensures that the provided message contains the correct interchain account owner address. executeMsg
will call the message handler and therefore execute the message.
# SDK security model
SDK modules on a chain are assumed to be trustworthy. For example, there are no checks to prevent an untrustworthy module from accessing the bank keeper.
The implementation of ICS-27 (opens new window) on ibc-go (opens new window) uses this assumption in its security considerations. The implementation assumes the authentication module will not try to open channels on owner addresses it does not control.
The implementation assumes other IBC application modules will not bind to ports within the ICS-27 (opens new window) namespace.
# Authentication module
The controller submodule (opens new window) is used for account registration and packet sending. It executes only logic required of all controllers of interchain accounts. The type of authentication used to manage the interchain accounts remains unspecified. There may exist many different types of authentication which are desirable for different use cases. Thus the purpose of the authentication module is to wrap the controller module with custom authentication logic.
In ibc-go (opens new window), authentication modules are connected to the controller chain via a middleware (opens new window) stack. The controller module is implemented as middleware (opens new window) and the authentication module is connected to the controller module as the base application of the middleware stack. To implement an authentication module, the IBCModule
interface must be fulfilled. By implementing the controller module as middleware, any amount of authentication modules can be created and connected to the controller module without writing redundant code.
The authentication module must:
- Authenticate interchain account owners
- Track the associated interchain account address for an owner
- Claim the channel capability in
OnChanOpenInit
- Send packets on behalf of an owner (after authentication)
The following IBCModule
(opens new window) callbacks must be implemented with appropriate custom logic:
The functions OnChanOpenTry
, OnChanOpenConfirm
, OnChanCloseInit
, and OnRecvPacket
must be defined to fulfill the IBCModule
interface, but they will never be called by the controller module, so they may error or panic.
The authentication module can begin registering interchain accounts by calling RegisterInterchainAccount
:
The authentication module can attempt to send a packet by calling SendTx
:
The data within an InterchainAccountPacketData
must be serialized using a format supported by the host chain. If the host chain is using the IBC-Go host chain submodule (opens new window), SerializeCosmosTx
should be used. If the InterchainAccountPacketData.Data
is serialized using a format not support by the host chain, the packet will not be successfully received.
Controller chains will be able to access the acknowledgement written into the host chain state once a relayer relays the acknowledgement. The acknowledgement bytes will be passed to the Authentication Module via the OnAcknowledgementPacket
callback. Authentication Modules are expected to know how to decode the acknowledgement.
If the controller chain is connected to a host chain using the host module on ibc-go, it may interpret the acknowledgement bytes as follows:
If the txMsgData.Data
is empty, the host chain is using SDK version > v0.45. The auth module should interpret the txMsgData.Responses
as follows:
A handler is needed to interpret what actions to perform based on the type url of the Any. A router could be used, or more simply a switch statement:
# Example integration
Here (opens new window) is an end-to-end working demo of interchain accounts. You will notice that it contains a similar app.go
to the generic one which follows.
To summarize, this section has explored:
- How an Interchain account (ICA) allows you to control an account on a "host chain" from a "controller chain".
- How the ICA application module can be set to function exclusively in the host or controller role, or for these submodules to be enabled and disabled dynamically using on-chain parameters.
- How an ICA authentication module is required on the controller chain for the creation and management of ICAs.