# 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
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:
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
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
OnChanOpenConfirm steps (controller & host chain), the
Active Channel for this interchain account is stored in state.
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
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
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.
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:
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
- Send packets on behalf of an owner (after authentication)
IBCModule (opens new window) callbacks must be implemented with appropriate custom logic:
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
The authentication module can attempt to send a packet by calling
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:
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.