Sean King
  • NEW!
    NEW!  Connect Ideas Across Notes
    Save time and share insights. With Paragraph Citation, you can quote others’ work with source info built in. If someone cites your note, you’ll see a card showing where it’s used—bringing notes closer together.
    Got it
      • Create new note
      • Create a note from template
        • Sharing URL Link copied
        • /edit
        • View mode
          • Edit mode
          • View mode
          • Book mode
          • Slide mode
          Edit mode View mode Book mode Slide mode
        • Customize slides
        • Note Permission
        • Read
          • Only me
          • Signed-in users
          • Everyone
          Only me Signed-in users Everyone
        • Write
          • Only me
          • Signed-in users
          • Everyone
          Only me Signed-in users Everyone
        • Engagement control Commenting, Suggest edit, Emoji Reply
      • Invite by email
        Invitee

        This note has no invitees

      • Publish Note

        Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note No publishing access yet

        Your note will be visible on your profile and discoverable by anyone.
        Your note is now live.
        This note is visible on your profile and discoverable online.
        Everyone on the web can find and read all notes of this public team.

        Your account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

        Your team account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

        Explore these features while you wait
        Complete general settings
        Bookmark and like published notes
        Write a few more notes
        Complete general settings
        Write a few more notes
        See published notes
        Unpublish note
        Please check the box to agree to the Community Guidelines.
        View profile
      • Commenting
        Permission
        Disabled Forbidden Owners Signed-in users Everyone
      • Enable
      • Permission
        • Forbidden
        • Owners
        • Signed-in users
        • Everyone
      • Suggest edit
        Permission
        Disabled Forbidden Owners Signed-in users Everyone
      • Enable
      • Permission
        • Forbidden
        • Owners
        • Signed-in users
      • Emoji Reply
      • Enable
      • Versions and GitHub Sync
      • Note settings
      • Note Insights New
      • Engagement control
      • Make a copy
      • Transfer ownership
      • Delete this note
      • Save as template
      • Insert from template
      • Import from
        • Dropbox
        • Google Drive
        • Gist
        • Clipboard
      • Export to
        • Dropbox
        • Google Drive
        • Gist
      • Download
        • Markdown
        • HTML
        • Raw HTML
    Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
    Create Create new note Create a note from template
    Menu
    Options
    Engagement control Make a copy Transfer ownership Delete this note
    Import from
    Dropbox Google Drive Gist Clipboard
    Export to
    Dropbox Google Drive Gist
    Download
    Markdown HTML Raw HTML
    Back
    Sharing URL Link copied
    /edit
    View mode
    • Edit mode
    • View mode
    • Book mode
    • Slide mode
    Edit mode View mode Book mode Slide mode
    Customize slides
    Note Permission
    Read
    Only me
    • Only me
    • Signed-in users
    • Everyone
    Only me Signed-in users Everyone
    Write
    Only me
    • Only me
    • Signed-in users
    • Everyone
    Only me Signed-in users Everyone
    Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note No publishing access yet

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.

    Your account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

    Your team account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

    Explore these features while you wait
    Complete general settings
    Bookmark and like published notes
    Write a few more notes
    Complete general settings
    Write a few more notes
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    ## Synopsis This standard document specifies packet data structure, state machine handling logic, and encoding details for the account management system over an IBC channel between separate chains. ### Motivation On Ethereum, there are two types of accounts: externally owned accounts, controlled by private keys, and contract accounts, controlled by their contract code ([ref](https://github.com/ethereum/wiki/wiki/White-Paper)). Similar to Ethereum's CA (contract accounts), interchain accounts are managed by another chain while retaining all the capabilities of a normal account (i.e. stake, send, vote, etc). While an Ethereum CA's contract logic is performed within Ethereum's EVM, interchain accounts are managed by another chain via IBC in a way such that the owner of the account retains full control over how it behaves. ### Definitions **TODO: Make this a table and add more useful definitions for used keywords throughout the spec** The IBC handler interface & IBC relayer module interface are as defined in [ICS 25](../ics-025-handler-interface) and [ICS 26](../ics-026-routing-module), respectively. ### Desired Properties - Permissionless - Fault containment: An interchain account must follow rules of its host chain, even in times of Byzantine behavior by the counterparty chain (the chain that manages the account) - The chain that controls the account must process the results asynchronously and according to the chain's logic. The acknowledgment message should contain a result of an error as described in [ics-4](https://github.com/cosmos/ibc/tree/master/spec/core/ics-004-channel-and-packet-semantics#acknowledgement-envelope). - Sending and receiving transactions will be processed in an ordered channel where packets are delivered exactly in the order in which they were sent. - Each ordered channel must only allow one interchain account to use it, otherwise, malicious users may be able to block transactions from being received. Practically, N accounts per N channels can be achieved by creating a new port for each user (owner of the interchain account) and creating a unique channel for each new registration request. Future versions of ics-27 will use partially ordered channels to allow multiple interchain accounts on the same channel to preserve account sequence ordering without being reliant on one another ## Technical Specification The implementation of interchain accounts is non-symmetric. This means that each sending chain can have a different way to generate an interchain account and each receiving chain can have a different set of transactions that may be deserialised in different ways. For example, chains that use the Cosmos SDK will deserialise tx bytes using Protobuf, but if the counterparty chain is a smart contract on Ethereum, it may deserialise tx bytes by an ABI that is a minimal serialisation algorithm for the smart contract. A chain can implement one or both parts to the interchain accounts protocol (sending and receiving). A sending chain registering and controlling an account does not necessarily have to allow other chains to register accounts on its own chain, and vice versa. The interchain account specification defines the general way to register an interchain account and transfer tx bytes. The counterparty chain is responsible for deserialising and executing the tx bytes, and the sending chain should know how the counterparty chain will handle the tx bytes in advance. Each chain-specific implementation should clearly document how serialization/deserialization of transactions happens and ensure the required packet data format is clearly outlined. Each chain must satisfy the following features to create an interchain account: - New interchain accounts must not conflict with existing ones - Each chain must keep track of which counterparty chain created each new interchain account The chain must reject the transaction and must not make a state transition in the following cases: - The IBC transaction fails to be deserialised - The authentication step on the receiving chain (where the interchain account is hosted) fails #### Known Issues ##### Ordered Channels In an ordered channel, the next packet cannot be relayed until the previous packet has been relayed. If the previous packet is timed out, the ordered channel will be closed and the next packet can never be relayed. If multiple distrusting accounts are allowed to use a single ordered channel this creates an attack vector whereby malicious users can block packets from being received in a timely manner. An example of this may be a malicious user sending hundreds of packets that are never paid for. Other users trying to use this channel will have to wait for all of these packets to be fully relayed or receive valid proof of these packets having timed out before their own packets can be relayed. Therefore, multiplexing N interchain accounts on 1 ordered channel is not viable. This specification assumes the following: N interchain accounts will exist on N ordered channels. ##### Unordered Channels An unordered channel lets packets be relayed in any order. A user can send 100 packets and never relay them. Another user submits one packet and can immediately relay just that one without having to relay all other packets. In theory interchain accounts can be implemented using an unordered channel so long as messages that are dependent on one another are packed into a single packet. However, this pattern differs from other standards such as how Tendermint's mempool operates. Rather than deviate from well defined standards for message processing it is recommended to not to use this approach or at a minimum clearly document how messages are processed on the receiving chain. ##### Partially Ordered Channels Interchain accounts are a perfect use case for partially ordered channels, whereby the order is based on account sequences. However, this has yet to be specified and implemented in IBC. As of the time of writing this specification the current progress can be tracked [here](https://github.com/cosmos/ibc/issues/550). ### Architecture Diagram ![](https://i.imgur.com/HX1h2u2.png) ### Authentication & Authorization The sending chain (the chain registering and controlling an account) will implement its own authentication and authorization, which will determine who can create an interchain account and what type of transactions the registered accounts can invoke. One example of this may be a cosmos SDK chain that only allows the creation of an interchain account on behalf of the chains distribution module (community pool), whereby actions this interchain account takes are determined by governance proposals voted on by the token holders of the sending chain. Another example may be a smart contract that registers an interchain account and has a specific set of actions it is authorized to take. The receiving chain must implement authentication with regard to ensuring that the incoming messages are sent by the owner of the targeted interchain account. With regards to authorization, it is up to each chain-specific implementation to decide if the hosted interchain accounts have the authority to invoke all of the chain's message types or only a subset. This configuration may be set up at module initialization. ### Data Structures ```typescript interface InterchainAccountModule { // Sending/Controlling side tryRegisterInterchainAccount(data: Uint8Array) tryRunTx(chainType: Uint8Array, data: any) // Recieving side createAccount(): Address deserialiseTx(txBytes: Uint8Array): Tx authenticateTx(tx: Tx): boolean runTx(tx: Tx): Result } ``` **A chain can implement the entire interface, or decide to implement only the sending or receiving parts of the protocol.** #### Sending Interface The `tryRegisterInterchainAccount` method in the `InterchainAccountModule` interface defines the way to request the creation of an interchain account on a remote chain. The remote chain creates an interchain account using its own account creation logic. Due to the limitation of ordered channels, the recommended way to achieve this when calling `tryRegisterInterchainAccount` is to dynamically bind a new port with the port id set as the address of the owner of the account (if the port is not already bound), invoke `OpenChanInit` via an IBC module which will initiate the handshake process and emit an event signaling to a relayer to generate a new channel between both chains. The remote chain can then create the interchain account in the `ChanOpenTry` callback as part of the channel creation handshake process defined in [ics-4](https://github.com/cosmos/ibc/tree/master/spec/core/ics-004-channel-and-packet-semantics). Once the `chanOpenAck` callback fires the handshake-originating (sending) chain can assume the account registration is successful. The `tryRunTx` method in the`InterchainAccountModule` interface defines the way to create an outgoing packet for a specific chain type. The chain type determines how the IBC account transaction should be constructed and serialised for the receiving chain. The sending side should know in advance how the receiving side expects the incoming IBC packet to be structured. #### Recieving Interface `createAccount` defines the way to determine the account's address by using the port & channel id. A newly created interchain account must not conflict with an existing account. Therefore, the host chain (the chain that the account will live on) must keep track of which blockchains have created an interchain account in order to verify the transaction signing authority in `authenticateTx`. `createAccount` should be called in the `chanOpenTry` callback as part of the channel creation handshake process defined in [ics-4](https://github.com/cosmos/ibc/tree/master/spec/core/ics-004-channel-and-packet-semantics). `authenticateTx` validates the transaction and checks that the signers in the transaction have the right permissions (are the owners of the account in question).` `runTx` executes a transaction after the transaction has been successfully authenticated. ### Packet Data `InterchainAccountPacketData` contains an array of messages that an interchain account can run and a memo string that is sent to the receiving chain. The example below is defined as a proto encoded message but each chain can encode this differently. This should be clearly defined in the documentation for each chain specific implementation. ```typescript message InterchainAccountPacketData { repeated google.protobuf.Any messages = 1; string memo = 2; } ``` The acknowledgement packet structure is defined as in [ics4](https://github.com/cosmos/cosmos-sdk/blob/v0.42.4/proto/ibc/core/channel/v1/channel.proto#L134-L147). The acknowledgement result should contain the chain-id and the address of the targetted interchain account. If an error occurs on the receiving chain the acknowledgement should contain the error message. ```typescript message Acknowledgement { // response contains either a result or an error and must be non-empty oneof response { bytes result = 21; string error = 22; } } ``` The ```InterchainAccountHook``` interface allows the source chain to receive results of executing transactions on an interchain account. ```typescript interface InterchainAccountHook { onTxSucceeded(sourcePort:string, sourceChannel:string, txBytes: Uint8Array) onTxFailed(sourcePort:string, sourceChannel:string, txBytes: Uint8Array) } ``` ### Port & channel setup Receiving chains (chains that will host interchain accounts) must always bind to a port with the id `interchain_account`. Sending chains will bind to ports dynamically, with each port id being the address of the interchain account owner. The example below assumes a module is implementing the entire `InterchainAccountModule` interface. The `setup` function must be called exactly once when the module is created (perhaps when the blockchain itself is initialized) to bind to the appropriate port. ```typescript function setup() { capability = routingModule.bindPort("interchain_account", ModuleCallbacks{ onChanOpenInit, onChanOpenTry, onChanOpenAck, onChanOpenConfirm, onChanCloseInit, onChanCloseConfirm, onRecvPacket, onTimeoutPacket, onAcknowledgePacket, onTimeoutPacketClose }) claimCapability("port", capability) } ``` Once the `setup` function has been called, channels can be created via the IBC routing module. ### Channel lifecycle management An interchain account module will accept new channels from any module on another machine, if and only if: - The channel being created is ordered - The version string is "ics27-1" ```typescript function onChanOpenInit( order: ChannelOrder, connectionHops: [Identifier], portIdentifier: Identifier, channelIdentifier: Identifier, counterpartyPortIdentifier: Identifier, counterpartyChannelIdentifier: Identifier, version: string) { // only ordered channels allowed abortTransactionUnless(order === ORDERED) // version not used at present abortTransactionUnless(version === "ics27-1") } ``` ```typescript function onChanOpenTry( order: ChannelOrder, connectionHops: [Identifier], portIdentifier: Identifier, channelIdentifier: Identifier, counterpartyPortIdentifier: Identifier, counterpartyChannelIdentifier: Identifier, version: string, counterpartyVersion: string) { // only unordered channels allowed abortTransactionUnless(order === ORDERED) // assert that version is "ics27-1" abortTransactionUnless(version === "ics27-1") abortTransactionUnless(counterpartyVersion === "ics27-1") // create an interchain account createAccount(counterpartyPortIdentifier, counterpartyChannelIdentifier) } ``` ```typescript function onChanOpenAck( portIdentifier: Identifier, channelIdentifier: Identifier, version: string) { // port has already been validated // assert that version is "ics27-1" abortTransactionUnless(version === "ics27-1") // state change to keep track of successfully registered interchain account confirmInterchainAccountRegistration() } ``` ```typescript function onChanOpenConfirm( portIdentifier: Identifier, channelIdentifier: Identifier) { } ``` ```typescript function onChanCloseInit( portIdentifier: Identifier, channelIdentifier: Identifier) { // no action necessary } ``` ```typescript function onChanCloseConfirm( portIdentifier: Identifier, channelIdentifier: Identifier) { // no action necessary } ``` ### Packet relay `onRecvPacket` is called by the routing module when a packet addressed to this module has been received. ```typescript function onRecvPacket(packet: Packet) { InterchainAccountPacketData data = packet.data const tx = deserialiseTx(packet.data.txBytes) abortTransactionUnless(authenticateTx(tx)) try { const result = runTx(tx) return Acknowledgement{ result: result } } catch (e) { // Return ack with error. return Acknowledgement{ error: e.message, } } ``` `onAcknowledgePacket` is called by the routing module when a packet sent by this module has been acknowledged. ```typescript function onAcknowledgePacket( packet: Packet, acknowledgement: bytes) { if (acknowledgement.result) { onTxSucceeded(packet.sourcePort, packet.sourceChannel, packet.data.data) } else { onTxFailed(packet.sourcePort, packet.sourceChannel, packet.data.data) } return } ``` **TODO: how to handle timeouts?** ```typescript function onTimeoutPacket(packet: Packet) { } ``` ```typescript function onTimeoutPacketClose(packet: Packet) { // nothing is necessary } ``` ## Example Implementation Repository for Cosmos-SDK implementation of ICS27: https://github.com/cosmos/interchain-accounts ## Copyright All content herein is licensed under [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0).

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password
    or
    Sign in via Google Sign in via Facebook Sign in via X(Twitter) Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    By signing in, you agree to our terms of service.

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully