Interchain Accountsについて調べてみた
2022/02/05
目次
IBCの問題点
cosmos-sdkに標準で備わっているモジュール(bankやgovなど)はどのブロックチェーン でも共通なので、IBCで相互接続が簡単に可能ですが、アプリケーション固有の機能はチェーンが個別にIBCの対応を行わなければいけません。そのため、
- 開発コストが増える
- チェーンによって対応のタイミングがバラバラ などの問題が発生します。
この問題に対応する機能がInterchain Accountsで、具体的には以下のようなことを行っています。
- すべてのモジュールの機能に対してアプリケーションレベルのIBCを作成することなく、ブロックチェーンのアプリケーション固有の機能にアクセスできるようにする
- IBC自体はチェーン間のデータ制御(転送、認証、順序づけなど)のプロトコルとして汎用化されていて、チェーン上のアプリ固有の制御部分はInterchain accountsがまかなう
- Interchain accountsのモジュールがIBCから受け取ったトランザクションをIBCを利用したトランザクションではなく、IBCを利用していない"普通のトランザクション"のふりをさせて、必要なモジュールに渡す
- この"普通のトランザクション"のふりをさせる部分に、トランザクションを送った元のチェーンのアカウントのみが制御できるInterchain accountを利用する
機能
機能はシンプルに大きく分けて2つあります。
IBCを介して新しいInterchain accountを決定論的に作成する トランザクションをInterchain accountに中継し、ターゲットとなるブロックチェーンに送信する
定義
- Host Chain
- Interchain accountが登録されているチェーン。Interchain accountが実行する命令(cosmos-sdkのmsgなど)を含むController ChainからIBCパケットをlistenする
- Controller Chain
- Host Chain上のInterchain accountを登録および制御するチェーン
- Controller Chainはアカウントを制御するためにIBC パケットをHost Chainに送信する
- Interchain Account
- Host Chain上のアカウント
- Controller Chainは秘密鍵を使用してトランザクションに署名するのではなく、IBC パケットをHost Chainに送信する。Host ChainはInterchain accountsが実行する必要のあるトランザクションを通知する
- Interchain Account Owner
- Controller Chain上のアカウント
- Host Chain上の全てのInterchain accountにはController Chain上にそれぞれの所有アカウントがある
ちょっとだけ詳細
Interchain Accountとtx実行時に何をしているのかを見るために少しコードを覗いてみました。
Register account
- InitInterchainAccount関数がInterchain accountを登録するためのエントリポイント
- Owner address(Host Chain上の自身のアカウント)を使用して新しいportIDを生成する
- portID = PortPrefix + Owner Address これはChannelOpenInit イベントを発行し、 Relayerがこれを拾う。アカウントは、Host ChainのOnChanOpenTryステップで登録される
// In Controller Chain
function InitInterchainAccount(connectionId: string, owner: string) returns (error) {
}
- OnChanOpenTry内でInterchain accountを生成し登録する
- Interchain accountはportIDを利用したModule Addressのサブアドレス。よって、これ自体ではトランザクションに署名できず、モジュールによって内部的に管理される。
// Host Chain
func (k Keeper) OnChanOpenTry(
ctx sdk.Context,
order channeltypes.Order,
connectionHops []string,
portID,
channelID string,
chanCap *capabilitytypes.Capability,
counterparty channeltypes.Counterparty,
counterpartyVersion string,
) (string, error) {
accAddress := icatypes.GenerateAddress(k.accountKeeper.GetModuleAddress(icatypes.ModuleName), counterparty.PortId)
k.RegisterInterchainAccount(ctx, accAddress, counterparty.PortId)
}
Execute Tx
- Controller Chainからmsgを受け取ると、msgを実行する前にAuthenticateTxが呼び出される。
// Host Chain
func (k Keeper) executeTx(ctx sdk.Context, sourcePort, destPort, destChannel string, msgs []sdk.Msg) error {
if err := k.AuthenticateTx(ctx, msgs, sourcePort); err != nil {
return err
}
// validate each message
// verify that interchain account owner is authorized to send each message
// execute each message
}
- AuthenticateTx は、msgのsignerが、IBC パケットが送信されたチャネルの相手側 portID に関連付けられたInterchain accountであることをチェックする。
function AuthenticateTx(msgs []Any, portId string) error {
// GetInterchainAccountAddress(portId)
// interchainAccountAddress != signer.String() return error
}
IBCのためのChannelを開くためのportIDに元のアドレスを使っていてそれを元に1対1でInterchain Accountを生成するので、元のチェーンで正しく署名したことを担保として、Interchain Accountでトランザクションが実行できるという理屈のようでした。
Interchain Accountsを使うと...
これを各チェーンが実装すれば、副次的にこんないいことがあるなと思ったことを挙げてみました。
- チェーン同士が繋がった世界でチェーン別にアカウント(private key)を持つ必要がなくなる
- スマートコントラクトがEVMで相互に作用するのと同じようにCosmosのアプリケーションが簡単に相互作用可能になる
- IBCによる相互接続のスピードが上げる
- IBCで相互接続するのはいいけど、チェーンごとにアカウントを管理しなければいけない状況はユーザーにとっては不幸だよなーと思っていたので、これを使えばどこかのチェーンでアカウントを持っていればいいので、ブロックチェーン上のアプリを使う上でのUXも向上するのでは?と思いました。
interchain accountsを使ったデモもすでに実装されていたので、試してみましたがちゃんと動いたので、試したい方はこちらから↓ https://github.com/cosmos/interchain-accounts-demo