From dcd2c3d06ebc0f648dce713375d0fdd5ac808256 Mon Sep 17 00:00:00 2001 From: Sean King Date: Tue, 27 Apr 2021 21:15:52 +0200 Subject: [PATCH 01/23] update: major revisions to ics-27 specification --- .../app/ics-027-interchain-accounts/README.md | 222 +++++++----------- 1 file changed, 87 insertions(+), 135 deletions(-) diff --git a/spec/app/ics-027-interchain-accounts/README.md b/spec/app/ics-027-interchain-accounts/README.md index d3f4aaa82..3dbcf7c18 100644 --- a/spec/app/ics-027-interchain-accounts/README.md +++ b/spec/app/ics-027-interchain-accounts/README.md @@ -20,110 +20,123 @@ On Ethereum, there are two types of accounts: externally owned accounts, control ### 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: Interchain account must follow rules of its host chain, even in times of Byzantine behaviour 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 result's code should be 0 if the transaction was successful and an error code other than 0 if the transaction failed. -- Sending and receiving transactions will be processed in an ordered channel where packets are delivered exactly in the order which they were sent. +- Fault containment: An interchain account must follow rules of its host chain, even in times of Byzantine behaviour 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 acknowledgement message should contain a result or 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 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 recieved. 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 get around this security issue and make the process more straight forward ## Technical Specification -The implementation of interchain account is non-symmetric. This means that each chain can have a different way to generate an interchain account and deserialise the transaction bytes and a different set of transactions that they can execute. For example, chains that use the Cosmos SDK will deserialise tx bytes using Amino or 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. -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 counterparty chain will handle the tx bytes in advance. +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 recieving chain a different way to deserialise the transaction bytes and a different set of transactions that they can execute. 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. -Each chain must satisfy following features to create a interchain account: +A chain can implement one or both parts to the interchain accounts protocol (sending and recieving). 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. -- New interchain accounts must not conflict with existing ones. -- Each chain must keep track of which counterparty chain created each new interchain account. +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. -Also, each chain must know how the counterparty chains serialise/deserialise transaction bytes in order to send transactions via IBC. And the counterparty chain must implement the process of safely executing IBC transactions by verifying the authority of the transaction's signers. +Each chain must satisfy the following features to create an interchain account: -The chain must reject the transaction and must not make a state transition in the following cases: +- New interchain accounts must not conflict with existing ones +- Each chain must keep track of which counterparty chain created each new interchain account -- The IBC transaction fails to be deserialised. -- The IBC transaction expects signers other than the interchain accounts made by the counterparty chain. +The chain must reject the transaction and must not make a state transition in the following cases: -It does not restrict how you can distinguish signers that was not made by the counterparty chain. But the most common way would be to record the account in state when the interchain account is registered and to verify that signers are recorded interchain account. +- The IBC transaction fails to be deserialised +- The authentication step on the recieving chain (where the interchain account is hosted) fails -### Data Structures +#### Known Issues +##### Ordered Channels +**TODO: Outline the security issue that exists with ordered channels** +##### Unordered Channels +**TODO: Outline why unordered channels cannot be used** -Each chain must implement the interfaces as defined in this section in order to support interchain accounts. +##### Partially Ordered Channels +**TODO: Outline why interchain accounts should use partially ordered channels in the future** -`tryRegisterIBCAccount` method in `IBCAccountModule` interface defines the way to request the creation of an IBC account on the host chain (or counterparty chain that the IBC account lives on). The host chain creates an IBC account using its account creation logic, which may use data within the packet (such as destination port, destination channel, etc) and other additional data for the process. The origin chain can receive the address of the account that was created from the acknowledge packet. +### Architecture Diagram +**TODO: Diagram with flow for registration + RunTX** -`tryRunTx` method in `IBCAccountModule` interface defines the way to create an outgoing packet for a specific `type`. `Type` indicates how the IBC account transaction should be constructed and serialised for the host chain. Generally, `type` indicates what blockchain framework the host chain was built on. +### Authentication & Authorization +The sending chain (the chain registering and controlling an account) will implement it's 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. -`createAccount` defines the way to determine the account's address by using the packet. If the host chain doesn't support a deterministic way to generate an address with data, it can be generated using the internal logic of the host chain. A newly created interchain account must not conflict with an existing account. Therefore, the host chain (on that the interchain account lives in) must keep track of which blockchains have created an interchain account within the host chain in order to verify the transaction signing authority in `authenticateTx`. +The recieving chain must implement authentication with regards to ensuring that the incoming messages are sent by the owner of the targetted interchain account. With regards to authorization, it is up to each chain specific implementation to decide if the hosted interchain accounts have authority to invoke all of the chains message types or only a subset. This configuration may be set up at module initialization. -`authenticateTx` validates the transaction and checks that the signers in the transaction have the right permissions. ` - -`runTx` executes a transaction after the transaction has been successfully authenticated. +### Data Structures ```typescript -type Tx = object - -interface IBCAccountModule { - tryRegisterIBCAccount(data: Uint8Array) +interface InterchainAccountModule { + // Sending/Controlling side + tryRegisterInterchainAccount(data: Uint8Array) tryRunTx(chainType: Uint8Array, data: any) - createAccount(packet: Packet, data: Uint8Array): Address + // Recieving side + createAccount(): Address deserialiseTx(txBytes: Uint8Array): Tx authenticateTx(tx: Tx): boolean runTx(tx: Tx): Result } ``` -`IBCAccountPacketData` specifies the type of packet. The `IBCAccountPacketData.data` is arbitrary and can be used for different purposes depending on the value of `IBCAccountPacketData.type`. +**A chain can implement the entire interface, or decide to implement only the sending or recieving parts of the protocol.** -When the value of `type` is `REGISTER`, `IBCAccountPacketData.data` can be used as information by which the account is created on the host chain. When the value of `type` is `RUNTX`, `IBCAccountPacketData.data` contains the tx bytes. -```typescript -// `Type` enumerator defines the packet type. -enum Type { - REGISTER, - RUNTX -} +#### 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 `chanOpenConfirm` 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 succesful. + + +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 recieving chain. The sending side should know in advance how the recieving side expects the incoming IBC packet to be structured. + +#### Recieving Interfacce -interface IBCAccountPacketData { - type: Type - data: Uint8Array +`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 `chanOpenConfirm` 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 string for passing useful information (**TODO: be more specific here**) to the recieving 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 data type describes the type of packet data and chain id and whether the result code of processing and the data of result if it is needed, and the reason for failure (if any). +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 result should contain the chain-id and a success message. **TODO: define standardized error messages.** ```typescript -interface IBCAccountPacketAcknowledgement { - type: Type - code: uint32 - data: Uint8Array - error: string +message Acknowledgement { + // response contains either a result or an error and must be non-empty + oneof response { + bytes result = 21; + string error = 22; + } } ``` -The ```IBCAccountHook``` interface allows the source chain to receive results of executing transactions on an interchain account. - +The ```InterchainAccountHook``` interface allows the source chain to receive results of executing transactions on an interchain account. ```typescript -interface IBCAccountHook { - onAccountCreated(sourcePort:string, sourceChannel:string, address: Address) +interface InterchainAccountHook { onTxSucceeded(sourcePort:string, sourceChannel:string, txBytes: Uint8Array) onTxFailed(sourcePort:string, sourceChannel:string, txBytes: Uint8Array) } ``` -### Subprotocols - -The subprotocols described herein should be implemented in an "interchain-account-bridge" module with access to a router and codec (decoder or unmarshaller) for the application and access to the IBC relayer module. - ### Port & channel setup +Recieving 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 `setup` function must be called exactly once when the module is created (perhaps when the blockchain itself is initialised) to bind to the appropriate port. +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 initialised) to bind to the appropriate port. ```typescript function setup() { - capability = routingModule.bindPort("ibcaccount", ModuleCallbacks{ + capability = routingModule.bindPort("interchain_account", ModuleCallbacks{ onChanOpenInit, onChanOpenTry, onChanOpenAck, @@ -139,19 +152,12 @@ function setup() { } ``` -Once the `setup` function has been called, channels can be created through the IBC routing module between instances of the ibc account module on separate chains. - -An administrator (with the permissions to create connections & channels on the host state machine) is responsible for setting up connections to other state machines & creating channels -to other instances of this module (or another module supporting this interface) on other chains. This specification defines packet handling semantics only, and defines them in such a fashion -that the module itself doesn't need to worry about what connections or channels might or might not exist at any point in time. - -### Routing module callbacks +Once the `setup` function has been called, channels can be created via the IBC routing module. ### Channel lifecycle management -Both machines `A` and `B` accept new channels from any module on another machine, if and only if: +An interchain account module will accept new channels from any module on another machine, if and only if: -- The other module is bound to the "ibcaccount" port. - The channel being created is ordered. - The version string is "ics27-1". @@ -166,8 +172,6 @@ function onChanOpenInit( version: string) { // only ordered channels allowed abortTransactionUnless(order === ORDERED) - // only allow channels to "ibcaccount" port on counterparty chain - abortTransactionUnless(counterpartyPortIdentifier === "ibcaccount") // version not used at present abortTransactionUnless(version === "ics27-1") } @@ -188,8 +192,8 @@ function onChanOpenTry( // assert that version is "ics27-1" abortTransactionUnless(version === "ics27-1") abortTransactionUnless(counterpartyVersion === "ics27-1") - // only allow channels to "ibcaccount" port on counterparty chain - abortTransactionUnless(counterpartyPortIdentifier === "ibcaccount") + // create an interchain account + createAccount() } ``` @@ -201,6 +205,8 @@ function onChanOpenAck( // 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() } ``` @@ -229,77 +235,37 @@ function onChanCloseConfirm( ``` ### Packet relay - -In plain English, between chains `A` and `B`. It will describe only the case that chain A wants to register an Interchain account on chain B and control it. Moreover, this system can also be applied the other way around. +**TODO: add description here** `onRecvPacket` is called by the routing module when a packet addressed to this module has been received. ```typescript function onRecvPacket(packet: Packet) { - IBCAccountPacketData data = packet.data - - switch (data.type) { - case Type.REGISTER: - try { - // Create an account by using the packet's data (destination port, destination channel, etc) and packet data's data. - const address = createAccount(packet, data.data) - - // Return ack with generated address. - return IBCAccountPacketAcknowledgement{ - type: Type.REGISTER, - code: 0, - data: address, - error: "", - } - } catch (e) { - // Return ack with error. - return IBCAccountPacketAcknowledgement{ - type: Type.REGISTER, - code: 1, - data: [], - error: e.message, - } - } - case Type.RUNTX: + InterchainAccountPacketData data = packet.data const tx = deserialiseTx(packet.data.txBytes) abortTransactionUnless(authenticateTx(tx)) try { const result = runTx(tx) - return IBCAccountPacketAcknowledgement{ - type: Type.RUNTX, - code: 0, - data: result.data, - error: "", + return Acknowledgement{ + result: result } } catch (e) { // Return ack with error. - return IBCAccountPacketAcknowledgement{ - type: Type.RUNTX, - code: e.code || 1, - data: [], + return Acknowledgement{ error: e.message, } - } - } } ``` `onAcknowledgePacket` is called by the routing module when a packet sent by this module has been acknowledged. +**TODO: define** ```typescript function onAcknowledgePacket( packet: Packet, acknowledgement: bytes) { - switch (ack.type) { - case Type.REGISTER: - if (ack.code === 0) { - onAccountCreated(packet.sourcePort, packet.sourceChannel, ack.data) - } - return - } - case Type.RUNTX: - if (ack.code === 0) { + if (acknowledgement.result) { onTxSucceeded(packet.sourcePort, packet.sourceChannel, packet.data.data) } else { onTxFailed(packet.sourcePort, packet.sourceChannel, packet.data.data) @@ -308,14 +274,12 @@ function onAcknowledgePacket( } ``` + +**TODO: how to handle timeouts?** ```typescript function onTimeoutPacket(packet: Packet) { - // Receiving chain should handle this event as if the tx in packet has failed - switch (ack.type) { - case Type.RUNTX: - onTxFailed(packet.sourcePort, packet.sourceChannel, packet.data.data) - return -} +** TODO: define +**} ``` ```typescript @@ -324,23 +288,9 @@ function onTimeoutPacketClose(packet: Packet) { } ``` -## Backwards Compatibility - -Not applicable. - -## Forwards Compatibility - -Not applicable. - ## Example Implementation -Repository for Cosmos-SDK implementation of ICS27: https://github.com/chainapsis/cosmos-sdk-interchain-account -Pseudocode for cosmos-sdk: https://github.com/everett-protocol/everett-hackathon/tree/master/x/interchain-account -POC for Interchain account on Ethereum: https://github.com/everett-protocol/ethereum-interchain-account - -## Other Implementations - -(links to or descriptions of other implementations) +Repository for Cosmos-SDK implementation of ICS27: https://github.com/cosmos/interchain-accounts ## History @@ -354,6 +304,8 @@ Dec 2, 2019 - Minor revisions (Add more specific description & Add interchain ac July 14, 2020 - Major revisions +April 27, 2021 - Redesign of ics27 specification + ## Copyright -All content herein is licensed under [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0). \ No newline at end of file +All content herein is licensed under [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0). From 124b8593c1eeab8e9d2eda24b2cbb364a068303a Mon Sep 17 00:00:00 2001 From: Sean King Date: Wed, 28 Apr 2021 08:59:03 +0200 Subject: [PATCH 02/23] update: adding known issues section --- spec/app/ics-027-interchain-accounts/README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/spec/app/ics-027-interchain-accounts/README.md b/spec/app/ics-027-interchain-accounts/README.md index 3dbcf7c18..a79b6b9d7 100644 --- a/spec/app/ics-027-interchain-accounts/README.md +++ b/spec/app/ics-027-interchain-accounts/README.md @@ -52,12 +52,13 @@ The chain must reject the transaction and must not make a state transition in th #### Known Issues ##### Ordered Channels -**TODO: Outline the security issue that exists with ordered channels** +In an ordered channel, packet 2 cannot be relayed until packet 1 has been relayed or a valid proof that packet 1 has timed out has been recieved. 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 recieved 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 recieve 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 -**TODO: Outline why unordered channels cannot be used** +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 recieving chain. ##### Partially Ordered Channels -**TODO: Outline why interchain accounts should use partially ordered channels in the future** +Interchain accounts is a perfect use case for partially ordered channels, whereby the order is based on account sequences. However, this has yet to be 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 **TODO: Diagram with flow for registration + RunTX** From 38244570e0188e76c38d6945841e767cae308625 Mon Sep 17 00:00:00 2001 From: Sean King Date: Wed, 28 Apr 2021 14:06:05 +0200 Subject: [PATCH 03/23] update: minor changes and adding architecture diagram for registration flow --- .../app/ics-027-interchain-accounts/README.md | 28 +++++++++---------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/spec/app/ics-027-interchain-accounts/README.md b/spec/app/ics-027-interchain-accounts/README.md index a79b6b9d7..a7b93f451 100644 --- a/spec/app/ics-027-interchain-accounts/README.md +++ b/spec/app/ics-027-interchain-accounts/README.md @@ -61,7 +61,9 @@ An unordered channel lets packets be relayed in any order. A user can send 100 p Interchain accounts is a perfect use case for partially ordered channels, whereby the order is based on account sequences. However, this has yet to be 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 -**TODO: Diagram with flow for registration + RunTX** +![](https://i.imgur.com/HX1h2u2.png) + + ### Authentication & Authorization The sending chain (the chain registering and controlling an account) will implement it's 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. @@ -87,21 +89,21 @@ interface InterchainAccountModule { #### 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 `chanOpenConfirm` 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 succesful. +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 succesful. 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 recieving chain. The sending side should know in advance how the recieving side expects the incoming IBC packet to be structured. #### Recieving Interfacce -`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 `chanOpenConfirm` 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). +`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 string for passing useful information (**TODO: be more specific here**) to the recieving 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. +`InterchainAccountPacketData` contains an array of messages that an interchain account can run and a memo string that is sent to the recieving 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 { @@ -110,7 +112,7 @@ message InterchainAccountPacketData { } ``` -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 result should contain the chain-id and a success message. **TODO: define standardized error messages.** +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 recieving chain the acknowledgement should contain the error message. ```typescript message Acknowledgement { @@ -159,8 +161,8 @@ Once the `setup` function has been called, channels can be created via the IBC r 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". +- The channel being created is ordered +- The version string is "ics27-1" ```typescript function onChanOpenInit( @@ -194,7 +196,7 @@ function onChanOpenTry( abortTransactionUnless(version === "ics27-1") abortTransactionUnless(counterpartyVersion === "ics27-1") // create an interchain account - createAccount() + createAccount(counterpartyPortIdentifier, counterpartyChannelIdentifier) } ``` @@ -215,7 +217,6 @@ function onChanOpenAck( function onChanOpenConfirm( portIdentifier: Identifier, channelIdentifier: Identifier) { - // accept channel confirmations, port has already been validated } ``` @@ -236,8 +237,6 @@ function onChanCloseConfirm( ``` ### Packet relay -**TODO: add description here** - `onRecvPacket` is called by the routing module when a packet addressed to this module has been received. ```typescript @@ -255,13 +254,12 @@ function onRecvPacket(packet: Packet) { // 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. -**TODO: define** ```typescript function onAcknowledgePacket( packet: Packet, @@ -279,8 +277,8 @@ function onAcknowledgePacket( **TODO: how to handle timeouts?** ```typescript function onTimeoutPacket(packet: Packet) { -** TODO: define -**} + +} ``` ```typescript From b3c56ceddce18ecfb5f87ef0a7cf3ccee2646467 Mon Sep 17 00:00:00 2001 From: Sean King Date: Wed, 28 Apr 2021 15:19:04 +0200 Subject: [PATCH 04/23] update: grammar --- .../app/ics-027-interchain-accounts/README.md | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/spec/app/ics-027-interchain-accounts/README.md b/spec/app/ics-027-interchain-accounts/README.md index a7b93f451..7cdbdc344 100644 --- a/spec/app/ics-027-interchain-accounts/README.md +++ b/spec/app/ics-027-interchain-accounts/README.md @@ -27,18 +27,18 @@ The IBC handler interface & IBC relayer module interface are as defined in [ICS ### Desired Properties - Permissionless -- Fault containment: An interchain account must follow rules of its host chain, even in times of Byzantine behaviour 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 acknowledgement message should contain a result or 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 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 recieved. 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 get around this security issue and make the process more straight forward +- 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 get around this security issue and make the process more straight forward ## 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 recieving chain a different way to deserialise the transaction bytes and a different set of transactions that they can execute. 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. +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 a different way to deserialise the transaction bytes and a different set of transactions that they can execute. 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 recieving). 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. +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. +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: @@ -48,17 +48,17 @@ Each chain must satisfy the following features to create an 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 recieving chain (where the interchain account is hosted) fails +- The authentication step on the receiving chain (where the interchain account is hosted) fails #### Known Issues ##### Ordered Channels -In an ordered channel, packet 2 cannot be relayed until packet 1 has been relayed or a valid proof that packet 1 has timed out has been recieved. 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 recieved 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 recieve 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. +In an ordered channel, packet 2 cannot be relayed until packet 1 has been relayed or a valid proof that packet 1 has timed out has been received. 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 recieving chain. +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 is a perfect use case for partially ordered channels, whereby the order is based on account sequences. However, this has yet to be 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). +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 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) @@ -66,9 +66,9 @@ Interchain accounts is a perfect use case for partially ordered channels, whereb ### Authentication & Authorization -The sending chain (the chain registering and controlling an account) will implement it's 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 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 recieving chain must implement authentication with regards to ensuring that the incoming messages are sent by the owner of the targetted interchain account. With regards to authorization, it is up to each chain specific implementation to decide if the hosted interchain accounts have authority to invoke all of the chains message types or only a subset. This configuration may be set up at module initialization. +The receiving chain must implement authentication with regard to ensuring that the incoming messages are sent by the owner of the targetted 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 @@ -85,14 +85,14 @@ interface InterchainAccountModule { } ``` -**A chain can implement the entire interface, or decide to implement only the sending or recieving parts of the protocol.** +**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 succesful. -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 recieving chain. The sending side should know in advance how the recieving side expects the incoming IBC packet to be structured. +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 Interfacce @@ -103,7 +103,7 @@ The `tryRunTx` method in the`InterchainAccountModule` interface defines the way `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 recieving 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. +`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 { @@ -112,7 +112,7 @@ message InterchainAccountPacketData { } ``` -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 recieving chain the acknowledgement should contain the error message. +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 { @@ -133,9 +133,9 @@ interface InterchainAccountHook { ``` ### Port & channel setup -Recieving 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. +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 initialised) to bind to the appropriate port. +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() { From 928ebe8dabb657165db40f5ec1ab307e9034668d Mon Sep 17 00:00:00 2001 From: Sean King Date: Fri, 30 Apr 2021 16:08:44 +0200 Subject: [PATCH 05/23] Update spec/app/ics-027-interchain-accounts/README.md Co-authored-by: Christopher Goes --- spec/app/ics-027-interchain-accounts/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/app/ics-027-interchain-accounts/README.md b/spec/app/ics-027-interchain-accounts/README.md index 7cdbdc344..f1652a9cc 100644 --- a/spec/app/ics-027-interchain-accounts/README.md +++ b/spec/app/ics-027-interchain-accounts/README.md @@ -68,7 +68,7 @@ Interchain accounts are a perfect use case for partially ordered channels, where ### 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 targetted 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. +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 From 4d4b7ca97680e2866e2b46aab0756fc523d111c1 Mon Sep 17 00:00:00 2001 From: Sean King Date: Tue, 4 May 2021 17:13:35 +0200 Subject: [PATCH 06/23] Update spec/app/ics-027-interchain-accounts/README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com> --- spec/app/ics-027-interchain-accounts/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/app/ics-027-interchain-accounts/README.md b/spec/app/ics-027-interchain-accounts/README.md index f1652a9cc..e0754f2ff 100644 --- a/spec/app/ics-027-interchain-accounts/README.md +++ b/spec/app/ics-027-interchain-accounts/README.md @@ -58,7 +58,7 @@ In an ordered channel, packet 2 cannot be relayed until packet 1 has been relaye 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 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). +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) From bec1cb5c19efa59ff234cb44706ad8e13070995d Mon Sep 17 00:00:00 2001 From: Sean King Date: Tue, 4 May 2021 17:14:14 +0200 Subject: [PATCH 07/23] Update spec/app/ics-027-interchain-accounts/README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com> --- spec/app/ics-027-interchain-accounts/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/app/ics-027-interchain-accounts/README.md b/spec/app/ics-027-interchain-accounts/README.md index e0754f2ff..0c871f19f 100644 --- a/spec/app/ics-027-interchain-accounts/README.md +++ b/spec/app/ics-027-interchain-accounts/README.md @@ -52,7 +52,7 @@ The chain must reject the transaction and must not make a state transition in th #### Known Issues ##### Ordered Channels -In an ordered channel, packet 2 cannot be relayed until packet 1 has been relayed or a valid proof that packet 1 has timed out has been received. 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. +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. From e68846454edf84a6fdfb96fef8bcf984db7ce9cf Mon Sep 17 00:00:00 2001 From: Sean King Date: Tue, 4 May 2021 17:17:18 +0200 Subject: [PATCH 08/23] Update spec/app/ics-027-interchain-accounts/README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com> --- spec/app/ics-027-interchain-accounts/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/app/ics-027-interchain-accounts/README.md b/spec/app/ics-027-interchain-accounts/README.md index 0c871f19f..5aa538e79 100644 --- a/spec/app/ics-027-interchain-accounts/README.md +++ b/spec/app/ics-027-interchain-accounts/README.md @@ -30,7 +30,7 @@ The IBC handler interface & IBC relayer module interface are as defined in [ICS - 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 get around this security issue and make the process more straight forward +- 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 From 073232ce567579d12da1654e26e51f9f9f4d4f4a Mon Sep 17 00:00:00 2001 From: Sean King Date: Tue, 4 May 2021 17:19:02 +0200 Subject: [PATCH 09/23] Update spec/app/ics-027-interchain-accounts/README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com> --- spec/app/ics-027-interchain-accounts/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/app/ics-027-interchain-accounts/README.md b/spec/app/ics-027-interchain-accounts/README.md index 5aa538e79..7a7b7612e 100644 --- a/spec/app/ics-027-interchain-accounts/README.md +++ b/spec/app/ics-027-interchain-accounts/README.md @@ -34,7 +34,7 @@ The IBC handler interface & IBC relayer module interface are as defined in [ICS ## 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 a different way to deserialise the transaction bytes and a different set of transactions that they can execute. 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. +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. From 26196d7627afc297062289d2cb9a4d868aace3b8 Mon Sep 17 00:00:00 2001 From: Sean King Date: Fri, 7 May 2021 19:33:38 +0200 Subject: [PATCH 10/23] Update spec/app/ics-027-interchain-accounts/README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com> --- spec/app/ics-027-interchain-accounts/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/app/ics-027-interchain-accounts/README.md b/spec/app/ics-027-interchain-accounts/README.md index 7a7b7612e..8b9727e63 100644 --- a/spec/app/ics-027-interchain-accounts/README.md +++ b/spec/app/ics-027-interchain-accounts/README.md @@ -89,7 +89,7 @@ interface InterchainAccountModule { #### 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 succesful. +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. From 12127f401cc4583273d466cbf2ff2b2c8142bd82 Mon Sep 17 00:00:00 2001 From: Sean King Date: Fri, 7 May 2021 19:34:31 +0200 Subject: [PATCH 11/23] Update spec/app/ics-027-interchain-accounts/README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com> --- spec/app/ics-027-interchain-accounts/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/app/ics-027-interchain-accounts/README.md b/spec/app/ics-027-interchain-accounts/README.md index 8b9727e63..2ece36058 100644 --- a/spec/app/ics-027-interchain-accounts/README.md +++ b/spec/app/ics-027-interchain-accounts/README.md @@ -94,7 +94,7 @@ The `tryRegisterInterchainAccount` method in the `InterchainAccountModule` inter 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 Interfacce +#### 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). From 671fa9e29df490780a96d1d4b158f8853f1f658c Mon Sep 17 00:00:00 2001 From: Sean King Date: Mon, 28 Jun 2021 18:33:33 +0200 Subject: [PATCH 12/23] adding definitions --- spec/app/ics-027-interchain-accounts/README.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/spec/app/ics-027-interchain-accounts/README.md b/spec/app/ics-027-interchain-accounts/README.md index 2ece36058..1cb5ec1e2 100644 --- a/spec/app/ics-027-interchain-accounts/README.md +++ b/spec/app/ics-027-interchain-accounts/README.md @@ -16,21 +16,23 @@ This standard document specifies packet data structure, state machine handling l ### 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. +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 contract accounts, interchain accounts are controlled by another chain (no private key) 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 a seperate chain via IBC in a way such that the owner of the account retains full control over how it behaves. ICS27-1 primarily targets the use cases of DAO investing and staking derivatives over IBC. ### Definitions -**TODO: Make this a table and add more useful definitions for used keywords throughout the spec** +- Interchain Account: An account on a host chain. An interchain account has all the capabilites of a normal account. However, rather than signing transactions with a private key, a controller chain will send IBC packets to the host chain which signal what transactions the interchain account should execute. +- Controller Chain: The chain registering and controlling an account on a host chain. The controller chain sends IBC packets to the host chain in order to control the account. +- 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) that the account will execute. 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 +- Fault containment: An interchain account must follow rules of its host chain, even in times of Byzantine behavior by the controller chain (the chain that manages the account) +- Sending and receiving transactions will be processed in an ordered channel where packets are delivered exactly in the order in which they were sent +- If a channel closes, the controller chain must be able to regain access to registered interchain accounts by simply opening a new channel +- Each interchain account is owned by a single account on the controller chain. Only the owner account on the controller chain is authorized to control the interchain account ## Technical Specification From 3cbdf75f68355d53a880ac4a0a857baf34d6102a Mon Sep 17 00:00:00 2001 From: Sean King Date: Tue, 29 Jun 2021 11:25:08 +0200 Subject: [PATCH 13/23] simplifying language and updating semantics --- .../app/ics-027-interchain-accounts/README.md | 109 +++++++----------- 1 file changed, 42 insertions(+), 67 deletions(-) diff --git a/spec/app/ics-027-interchain-accounts/README.md b/spec/app/ics-027-interchain-accounts/README.md index 1cb5ec1e2..10b167e72 100644 --- a/spec/app/ics-027-interchain-accounts/README.md +++ b/spec/app/ics-027-interchain-accounts/README.md @@ -5,7 +5,7 @@ stage: Draft category: IBC/TAO requires: 25, 26 kind: instantiation -author: Tony Yun , Dogemos +author: Tony Yun , Dogemos , Sean King created: 2019-08-01 modified: 2020-07-14 --- @@ -16,19 +16,20 @@ This standard document specifies packet data structure, state machine handling l ### 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 contract accounts, interchain accounts are controlled by another chain (no private key) 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 a seperate chain via IBC in a way such that the owner of the account retains full control over how it behaves. ICS27-1 primarily targets the use cases of DAO investing and staking derivatives over IBC. +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 contract accounts, interchain accounts are controlled by another chain (not a private key) 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 a seperate chain via IBC in a way such that the owner of the account retains full control over how it behaves. ICS27-1 primarily targets the use cases of DAO investing and staking derivatives over IBC. -### Definitions +### Definitions -- Interchain Account: An account on a host chain. An interchain account has all the capabilites of a normal account. However, rather than signing transactions with a private key, a controller chain will send IBC packets to the host chain which signal what transactions the interchain account should execute. -- Controller Chain: The chain registering and controlling an account on a host chain. The controller chain sends IBC packets to the host chain in order to control the account. -- 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) that the account will execute. +- Interchain Account: An account on a host chain. An interchain account has all the capabilites of a normal account. However, rather than signing transactions with a private key, a controller chain will send IBC packets to the host chain which signal what transactions the interchain account should execute +- Interchain Account Owner: An account on the controller chain. Every interchain account on a host chain has a respective owner account on the controller chain +- Controller Chain: The chain registering and controlling an account on a host chain. The controller chain sends IBC packets to the host chain in order to control the account +- 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) that the interchain account will execute 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 +- Permissionless - Fault containment: An interchain account must follow rules of its host chain, even in times of Byzantine behavior by the controller chain (the chain that manages the account) - Sending and receiving transactions will be processed in an ordered channel where packets are delivered exactly in the order in which they were sent - If a channel closes, the controller chain must be able to regain access to registered interchain accounts by simply opening a new channel @@ -36,53 +37,41 @@ The IBC handler interface & IBC relayer module interface are as defined in [ICS ## 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 (controlling and hosting). A controller chain that registers accounts on other host chains (that support interchain accounts) does not necessarily have to allow other controller chains to register accounts on its own chain, and vice versa. -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. +This specification defines the general way to register an interchain account and transfer tx bytes. The host chain is responsible for deserialising and executing the tx bytes, and the controller chain should know how the host chain will handle the tx bytes in advance (Cosmos SDK chains will deserialize using Protobuf). -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. +### Authentication & Authorization -##### 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). +For the controller chain to register an interchain account on a host chain, first the controlling side must bind a new port to the interchain account module with the id `ics27-1-{owner-address}` where `{owner-address}` is the account address of the interchain account owner. This port will be used to create channels between the controller & host chain for a specific owner/interchain account pair. Only the account with `{owner-address}` matching the bound port will be authorized to send IBC packets over channels created with `SourcePort` `ics27-1-{owner-address}`. The host chain trusts that each controller chain will enforce this port registration and access. -### Architecture Diagram -![](https://i.imgur.com/HX1h2u2.png) +In the case of a channel closing, both the controller and host chain should keep track of an `active-channel` for each registered interchain account. The `active-channel` is set during the channel creation handshake process. If a channel closes, a new channel can be opened with the same source port, allowing access to the interchain account on the host chain. +An active channel can look like: -### 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. +```typescript +{ + // Controller Chain + SourcePortId: `ics-27-1-cosmos1mjk79fjjgpplak5wq838w0yd982gzkyfrk07am`, + SourceChannelId: `channel-1`, + // Host Chain + CounterPartyPortId: `interchain-accounts`, + CounterPartyChannelId: `channel-2`, +} +```` ### Data Structures ```typescript interface InterchainAccountModule { - // Sending/Controlling side - tryRegisterInterchainAccount(data: Uint8Array) - tryRunTx(chainType: Uint8Array, data: any) - // Recieving side - createAccount(): Address + // Controlling side + initInterchainAccount(owner: string) // binds a new port with id `ics27-1-{owner-address}` + tryRunTx(owner: string, data: any) // sends an IBC packet containing tx bytes over the active channel for the respective owner + // Host side + createInterchainAccount(): Address deserialiseTx(txBytes: Uint8Array): Tx - authenticateTx(tx: Tx): boolean runTx(tx: Tx): Result } ``` @@ -91,21 +80,19 @@ interface InterchainAccountModule { #### 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 `initInterchainAccount` method in the `InterchainAccountModule` interface defines how the controller chain requests the creation of an interchain account on a host chain. Calling `initInterchainAccount` binds a new port with id `ics27-1-{owner-address}` and calls `OpenChanInit` via the IBC module which will initiate the handshake process and emit an event signaling to a relayer to create a new channel between both chains. The host 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 is successful the handshake-originating (controller) chain can assume the account registration is succesful. -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 +The `tryRunTx` method in the`InterchainAccountModule` creates an outgoing IBC packet containing tx bytes (e.g. cosmos SDK messages) that a specifc interchain account should execute. -`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). +#### Recieving Interfacce -`authenticateTx` validates the transaction and checks that the signers in the transaction have the right permissions (are the owners of the account in question).` +`createInterchainAccount` A newly created interchain account must not conflict with an existing account. `createInterchainAccount` 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). -`runTx` executes a transaction after the transaction has been successfully authenticated. +`runTx` executes a transaction based on the IBC packet recieved from the controller chain. ### 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. +`InterchainAccountPacketData` contains an array of messages that an interchain account can execute and a memo string that is sent to the host chain. ```typescript message InterchainAccountPacketData { @@ -114,7 +101,7 @@ message InterchainAccountPacketData { } ``` -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. +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). If an error occurs on the host chain the acknowledgement should contain the error message. ```typescript message Acknowledgement { @@ -126,7 +113,7 @@ message Acknowledgement { } ``` -The ```InterchainAccountHook``` interface allows the source chain to receive results of executing transactions on an interchain account. +The ```InterchainAccountHook``` interface allows the controller chain to receive results of executed transactions on the host chain. ```typescript interface InterchainAccountHook { onTxSucceeded(sourcePort:string, sourceChannel:string, txBytes: Uint8Array) @@ -135,7 +122,7 @@ interface InterchainAccountHook { ``` ### 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 interchain account module on a host chain must always bind to a port with the id `interchain_account`. Controller chains will bind to ports dynamically, with each port id set as `ics27-1-{owner-address}`. 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. @@ -198,7 +185,7 @@ function onChanOpenTry( abortTransactionUnless(version === "ics27-1") abortTransactionUnless(counterpartyVersion === "ics27-1") // create an interchain account - createAccount(counterpartyPortIdentifier, counterpartyChannelIdentifier) + createInterchainAccount(counterpartyPortIdentifier, counterpartyChannelIdentifier) } ``` @@ -211,7 +198,7 @@ function onChanOpenAck( // assert that version is "ics27-1" abortTransactionUnless(version === "ics27-1") // state change to keep track of successfully registered interchain account - confirmInterchainAccountRegistration() + setActiveChannel(SourcePortId) } ``` @@ -219,6 +206,7 @@ function onChanOpenAck( function onChanOpenConfirm( portIdentifier: Identifier, channelIdentifier: Identifier) { + setActiveChannel(CounterPartyPortId) } ``` @@ -275,20 +263,6 @@ function onAcknowledgePacket( } ``` - -**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 @@ -310,3 +284,4 @@ April 27, 2021 - Redesign of ics27 specification ## Copyright All content herein is licensed under [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0). + From 143057240fbe58f72b52f141f2da2f7c7c754a7d Mon Sep 17 00:00:00 2001 From: Sean King Date: Tue, 29 Jun 2021 16:08:01 +0200 Subject: [PATCH 14/23] remote auth step --- spec/app/ics-027-interchain-accounts/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/spec/app/ics-027-interchain-accounts/README.md b/spec/app/ics-027-interchain-accounts/README.md index 10b167e72..51708d837 100644 --- a/spec/app/ics-027-interchain-accounts/README.md +++ b/spec/app/ics-027-interchain-accounts/README.md @@ -233,7 +233,6 @@ function onChanCloseConfirm( function onRecvPacket(packet: Packet) { InterchainAccountPacketData data = packet.data const tx = deserialiseTx(packet.data.txBytes) - abortTransactionUnless(authenticateTx(tx)) try { const result = runTx(tx) From edf9fb3258f08da8ce4e78df4aa1331b1233d4b1 Mon Sep 17 00:00:00 2001 From: Sean King Date: Tue, 6 Jul 2021 12:52:36 +0200 Subject: [PATCH 15/23] adding connection-id to port id & unset active channel on closing --- .../app/ics-027-interchain-accounts/README.md | 36 +++++++++++-------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/spec/app/ics-027-interchain-accounts/README.md b/spec/app/ics-027-interchain-accounts/README.md index 51708d837..6f03197d6 100644 --- a/spec/app/ics-027-interchain-accounts/README.md +++ b/spec/app/ics-027-interchain-accounts/README.md @@ -30,10 +30,10 @@ The IBC handler interface & IBC relayer module interface are as defined in [ICS ### Desired Properties - Permissionless -- Fault containment: An interchain account must follow rules of its host chain, even in times of Byzantine behavior by the controller chain (the chain that manages the account) -- Sending and receiving transactions will be processed in an ordered channel where packets are delivered exactly in the order in which they were sent +- The ordering of transactions sent to an interchain account on a host chain must be maintained. Transactions should be executed by an interchain account in the order in which they are sent by the controller chain - If a channel closes, the controller chain must be able to regain access to registered interchain accounts by simply opening a new channel - Each interchain account is owned by a single account on the controller chain. Only the owner account on the controller chain is authorized to control the interchain account +- The controller chain must store the account address of the interchain account on the host chain ## Technical Specification @@ -43,10 +43,10 @@ This specification defines the general way to register an interchain account and ### Authentication & Authorization -For the controller chain to register an interchain account on a host chain, first the controlling side must bind a new port to the interchain account module with the id `ics27-1-{owner-address}` where `{owner-address}` is the account address of the interchain account owner. This port will be used to create channels between the controller & host chain for a specific owner/interchain account pair. Only the account with `{owner-address}` matching the bound port will be authorized to send IBC packets over channels created with `SourcePort` `ics27-1-{owner-address}`. The host chain trusts that each controller chain will enforce this port registration and access. +For the controller chain to register an interchain account on a host chain, first the controlling side must bind a new port to the interchain account module with the id `ics27-1-{connection-number}-{owner-address}` where `{owner-address}` is the account address of the interchain account owner & connection number is the number parsed from the connection id (e.g. `connection-1` would have a connection number of `1`). This port will be used to create channels between the controller & host chain for a specific owner/interchain account pair. Only the account with `{owner-address}` matching the bound port will be authorized to send IBC packets over channels created with `SourcePort` `ics27-1-{connection-number}-{owner-address}`. The host chain trusts that each controller chain will enforce this port registration and access. -In the case of a channel closing, both the controller and host chain should keep track of an `active-channel` for each registered interchain account. The `active-channel` is set during the channel creation handshake process. If a channel closes, a new channel can be opened with the same source port, allowing access to the interchain account on the host chain. +The controller and host chain should keep track of an `active-channel` for each registered interchain account. The `active-channel` is set during the channel creation handshake process. If a channel closes, the `active-channel` should be unset. A new channel can be opened with the same source port, allowing access to the interchain account on the host chain. An active channel can look like: @@ -57,10 +57,10 @@ An active channel can look like: SourcePortId: `ics-27-1-cosmos1mjk79fjjgpplak5wq838w0yd982gzkyfrk07am`, SourceChannelId: `channel-1`, // Host Chain - CounterPartyPortId: `interchain-accounts`, + CounterPartyPortId: `interchain_account`, CounterPartyChannelId: `channel-2`, } -```` +``` ### Data Structures @@ -68,11 +68,11 @@ An active channel can look like: interface InterchainAccountModule { // Controlling side initInterchainAccount(owner: string) // binds a new port with id `ics27-1-{owner-address}` - tryRunTx(owner: string, data: any) // sends an IBC packet containing tx bytes over the active channel for the respective owner + trySendTx(owner: string, data: any, connectionId: string) // sends an IBC packet containing tx bytes over the active channel for the respective owner // Host side createInterchainAccount(): Address deserialiseTx(txBytes: Uint8Array): Tx - runTx(tx: Tx): Result + executeTx(tx: Tx): Result } ``` @@ -80,16 +80,16 @@ interface InterchainAccountModule { #### Sending Interface -The `initInterchainAccount` method in the `InterchainAccountModule` interface defines how the controller chain requests the creation of an interchain account on a host chain. Calling `initInterchainAccount` binds a new port with id `ics27-1-{owner-address}` and calls `OpenChanInit` via the IBC module which will initiate the handshake process and emit an event signaling to a relayer to create a new channel between both chains. The host 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 is successful the handshake-originating (controller) chain can assume the account registration is succesful. +The `initInterchainAccount` method in the `InterchainAccountModule` interface defines how the controller chain requests the creation of an interchain account on a host chain. Calling `initInterchainAccount` binds a new port with id `ics27-1-{connection-number}-{owner-address}` and calls `OpenChanInit` via the IBC module which will initiate the handshake process and emit an event signaling to a relayer to create a new channel between both chains. The host 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 is successful the handshake-originating (controller) chain can assume the account registration is succesful. -The `tryRunTx` method in the`InterchainAccountModule` creates an outgoing IBC packet containing tx bytes (e.g. cosmos SDK messages) that a specifc interchain account should execute. +The `trySendTx` method in the`InterchainAccountModule` creates an outgoing IBC packet containing tx bytes (e.g. cosmos SDK messages) that a specifc interchain account should execute. #### Recieving Interfacce `createInterchainAccount` A newly created interchain account must not conflict with an existing account. `createInterchainAccount` 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). -`runTx` executes a transaction based on the IBC packet recieved from the controller chain. +`executeTx` executes a transaction based on the IBC packet recieved from the controller chain. ### Packet Data `InterchainAccountPacketData` contains an array of messages that an interchain account can execute and a memo string that is sent to the host chain. @@ -122,7 +122,8 @@ interface InterchainAccountHook { ``` ### Port & channel setup -The interchain account module on a host chain must always bind to a port with the id `interchain_account`. Controller chains will bind to ports dynamically, with each port id set as `ics27-1-{owner-address}`. + +The interchain account module on a host chain must always bind to a port with the id `interchain_account`. Controller chains will bind to ports dynamically, with each port id set as `ics27-1-{connection-id}-{owner-address}`. 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. @@ -164,8 +165,12 @@ function onChanOpenInit( version: string) { // only ordered channels allowed abortTransactionUnless(order === ORDERED) + // only allow channels to "ibcaccount" port on counterparty chain + abortTransactionUnless(counterpartyPortIdentifier === "ibcaccount") // version not used at present abortTransactionUnless(version === "ics27-1") + // Only open the channel if there is no active channel already set (with status OPEN) + abortTransactionUnless(activeChannel === nil) } ``` @@ -222,7 +227,7 @@ function onChanCloseInit( function onChanCloseConfirm( portIdentifier: Identifier, channelIdentifier: Identifier) { - // no action necessary + unsetActiveChannel(sourcePort) } ``` @@ -234,7 +239,7 @@ function onRecvPacket(packet: Packet) { InterchainAccountPacketData data = packet.data const tx = deserialiseTx(packet.data.txBytes) try { - const result = runTx(tx) + const result = executeTx(tx) return Acknowledgement{ result: result @@ -255,6 +260,8 @@ function onAcknowledgePacket( acknowledgement: bytes) { if (acknowledgement.result) { onTxSucceeded(packet.sourcePort, packet.sourceChannel, packet.data.data) + // Sets the interchainAccount address on the controller side for a given owner + setInterchainAccountAddress(sourcePort, result) } else { onTxFailed(packet.sourcePort, packet.sourceChannel, packet.data.data) } @@ -284,3 +291,4 @@ April 27, 2021 - Redesign of ics27 specification All content herein is licensed under [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0). + From 0d767e13e0eee3cd499ab4baa650c99cc145b9af Mon Sep 17 00:00:00 2001 From: Sean King Date: Tue, 13 Jul 2021 13:28:53 +0200 Subject: [PATCH 16/23] fix: grammar --- .../app/ics-027-interchain-accounts/README.md | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/spec/app/ics-027-interchain-accounts/README.md b/spec/app/ics-027-interchain-accounts/README.md index 6f03197d6..88cf7bbaa 100644 --- a/spec/app/ics-027-interchain-accounts/README.md +++ b/spec/app/ics-027-interchain-accounts/README.md @@ -16,13 +16,13 @@ This standard document specifies packet data structure, state machine handling l ### 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 contract accounts, interchain accounts are controlled by another chain (not a private key) 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 a seperate chain via IBC in a way such that the owner of the account retains full control over how it behaves. ICS27-1 primarily targets the use cases of DAO investing and staking derivatives over IBC. +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 contract accounts, interchain accounts are controlled by another chain (not a private key) 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 a separate chain via IBC in a way such that the owner of the account retains full control over how it behaves. ICS27-1 primarily targets the use cases of DAO investing and staking derivatives over IBC. ### Definitions -- Interchain Account: An account on a host chain. An interchain account has all the capabilites of a normal account. However, rather than signing transactions with a private key, a controller chain will send IBC packets to the host chain which signal what transactions the interchain account should execute +- Interchain Account: 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 will send IBC packets to the host chain which signal what transactions the interchain account should execute - Interchain Account Owner: An account on the controller chain. Every interchain account on a host chain has a respective owner account on the controller chain -- Controller Chain: The chain registering and controlling an account on a host chain. The controller chain sends IBC packets to the host chain in order to control the account +- Controller Chain: The chain registering and controlling an account on a host chain. The controller chain sends IBC packets to the host chain to control the account - 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) that the interchain account will execute 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. @@ -37,9 +37,9 @@ The IBC handler interface & IBC relayer module interface are as defined in [ICS ## Technical Specification -A chain can implement one or both parts to the interchain accounts protocol (controlling and hosting). A controller chain that registers accounts on other host chains (that support interchain accounts) does not necessarily have to allow other controller chains to register accounts on its own chain, and vice versa. +A chain can implement one or both parts of the interchain accounts protocol (controlling and hosting). A controller chain that registers accounts on other host chains (that support interchain accounts) does not necessarily have to allow other controller chains to register accounts on its chain, and vice versa. -This specification defines the general way to register an interchain account and transfer tx bytes. The host chain is responsible for deserialising and executing the tx bytes, and the controller chain should know how the host chain will handle the tx bytes in advance (Cosmos SDK chains will deserialize using Protobuf). +This specification defines the general way to register an interchain account and transfer tx bytes. The host chain is responsible for deserializing and executing the tx bytes, and the controller chain should know how the host chain will handle the tx bytes in advance (Cosmos SDK chains will deserialize using Protobuf). ### Authentication & Authorization @@ -48,7 +48,7 @@ For the controller chain to register an interchain account on a host chain, firs The controller and host chain should keep track of an `active-channel` for each registered interchain account. The `active-channel` is set during the channel creation handshake process. If a channel closes, the `active-channel` should be unset. A new channel can be opened with the same source port, allowing access to the interchain account on the host chain. -An active channel can look like: +An active channel can look like this: ```typescript @@ -72,6 +72,7 @@ interface InterchainAccountModule { // Host side createInterchainAccount(): Address deserialiseTx(txBytes: Uint8Array): Tx + authenticateTx(messages: []sdk.Message, portId: string): Error executeTx(tx: Tx): Result } ``` @@ -80,16 +81,16 @@ interface InterchainAccountModule { #### Sending Interface -The `initInterchainAccount` method in the `InterchainAccountModule` interface defines how the controller chain requests the creation of an interchain account on a host chain. Calling `initInterchainAccount` binds a new port with id `ics27-1-{connection-number}-{owner-address}` and calls `OpenChanInit` via the IBC module which will initiate the handshake process and emit an event signaling to a relayer to create a new channel between both chains. The host 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 is successful the handshake-originating (controller) chain can assume the account registration is succesful. +The `initInterchainAccount` method in the `InterchainAccountModule` interface defines how the controller chain requests the creation of an interchain account on a host chain. Calling `initInterchainAccount` binds a new port with id `ics27-1-{connection-number}-{owner-address}` and calls `OpenChanInit` via the IBC module which will initiate the handshake process and emit an event signaling to a relayer to create a new channel between both chains. The host 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 is successful the handshake-originating (controller) chain can assume the account registration is successful. -The `trySendTx` method in the`InterchainAccountModule` creates an outgoing IBC packet containing tx bytes (e.g. cosmos SDK messages) that a specifc interchain account should execute. +The `trySendTx` method in the`InterchainAccountModule` creates an outgoing IBC packet containing tx bytes (e.g. cosmos SDK messages) that a specific interchain account should execute. #### Recieving Interfacce `createInterchainAccount` A newly created interchain account must not conflict with an existing account. `createInterchainAccount` 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). -`executeTx` executes a transaction based on the IBC packet recieved from the controller chain. +`executeTx` executes a transaction based on the IBC packet received from the controller chain. ### Packet Data `InterchainAccountPacketData` contains an array of messages that an interchain account can execute and a memo string that is sent to the host chain. @@ -101,7 +102,7 @@ message InterchainAccountPacketData { } ``` -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). If an error occurs on the host chain the acknowledgement should contain the error message. +The acknowledgment 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). If an error occurs on the host chain the acknowledgment should contain the error message. ```typescript message Acknowledgement { @@ -291,4 +292,3 @@ April 27, 2021 - Redesign of ics27 specification All content herein is licensed under [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0). - From 432da446b584b490c774b19648859a0dfca8a034 Mon Sep 17 00:00:00 2001 From: Sean King Date: Tue, 13 Jul 2021 14:41:26 +0200 Subject: [PATCH 17/23] adding check for counter party port + timeout --- .../app/ics-027-interchain-accounts/README.md | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/spec/app/ics-027-interchain-accounts/README.md b/spec/app/ics-027-interchain-accounts/README.md index 88cf7bbaa..f1d72712f 100644 --- a/spec/app/ics-027-interchain-accounts/README.md +++ b/spec/app/ics-027-interchain-accounts/README.md @@ -166,8 +166,8 @@ function onChanOpenInit( version: string) { // only ordered channels allowed abortTransactionUnless(order === ORDERED) - // only allow channels to "ibcaccount" port on counterparty chain - abortTransactionUnless(counterpartyPortIdentifier === "ibcaccount") + // only allow channels to "interchain_account" port on counterparty chain + abortTransactionUnless(counterpartyPortIdentifier === "interchain_account") // version not used at present abortTransactionUnless(version === "ics27-1") // Only open the channel if there is no active channel already set (with status OPEN) @@ -187,6 +187,7 @@ function onChanOpenTry( counterpartyVersion: string) { // only unordered channels allowed abortTransactionUnless(order === ORDERED) + // assert that version is "ics27-1" abortTransactionUnless(version === "ics27-1") abortTransactionUnless(counterpartyVersion === "ics27-1") @@ -220,7 +221,7 @@ function onChanOpenConfirm( function onChanCloseInit( portIdentifier: Identifier, channelIdentifier: Identifier) { - // no action necessary + unsetActiveChannel(CounterPartyPortId) } ``` @@ -228,7 +229,7 @@ function onChanCloseInit( function onChanCloseConfirm( portIdentifier: Identifier, channelIdentifier: Identifier) { - unsetActiveChannel(sourcePort) + unsetActiveChannel(SourcePort) } ``` @@ -270,6 +271,16 @@ function onAcknowledgePacket( } ``` +```typescript +function onTimeoutPacket(packet: Packet) { + // Receiving chain should handle this event as if the tx in packet has failed + switch (ack.type) { + case Type.RUNTX: + onTxFailed(packet.sourcePort, packet.sourceChannel, packet.data.data) + return +} +``` + ## Example Implementation Repository for Cosmos-SDK implementation of ICS27: https://github.com/cosmos/interchain-accounts @@ -292,3 +303,4 @@ April 27, 2021 - Redesign of ics27 specification All content herein is licensed under [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0). + From 00db346d76d3ea2728a4f1bd1ecb1898436427d7 Mon Sep 17 00:00:00 2001 From: Sean King Date: Fri, 16 Jul 2021 15:37:14 +0200 Subject: [PATCH 18/23] updating based on comments --- spec/app/ics-027-interchain-accounts/README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/spec/app/ics-027-interchain-accounts/README.md b/spec/app/ics-027-interchain-accounts/README.md index f1d72712f..af77b8568 100644 --- a/spec/app/ics-027-interchain-accounts/README.md +++ b/spec/app/ics-027-interchain-accounts/README.md @@ -33,7 +33,7 @@ The IBC handler interface & IBC relayer module interface are as defined in [ICS - The ordering of transactions sent to an interchain account on a host chain must be maintained. Transactions should be executed by an interchain account in the order in which they are sent by the controller chain - If a channel closes, the controller chain must be able to regain access to registered interchain accounts by simply opening a new channel - Each interchain account is owned by a single account on the controller chain. Only the owner account on the controller chain is authorized to control the interchain account -- The controller chain must store the account address of the interchain account on the host chain +- The controller chain must store the account address of the interchain account ## Technical Specification @@ -43,7 +43,7 @@ This specification defines the general way to register an interchain account and ### Authentication & Authorization -For the controller chain to register an interchain account on a host chain, first the controlling side must bind a new port to the interchain account module with the id `ics27-1-{connection-number}-{owner-address}` where `{owner-address}` is the account address of the interchain account owner & connection number is the number parsed from the connection id (e.g. `connection-1` would have a connection number of `1`). This port will be used to create channels between the controller & host chain for a specific owner/interchain account pair. Only the account with `{owner-address}` matching the bound port will be authorized to send IBC packets over channels created with `SourcePort` `ics27-1-{connection-number}-{owner-address}`. The host chain trusts that each controller chain will enforce this port registration and access. +For the controller chain to register an interchain account on a host chain, first the controlling side must bind a new port to the interchain account module with the id `ics27-1-{connection-number}-{counterparty-connection-number}-{owner-address}` where `{owner-address}` is the account address of the interchain account owner & connection number is the number parsed from the connection id (e.g. `connection-1` would have a connection number of `1`). This port will be used to create channels between the controller & host chain for a specific owner/interchain account pair. Only the account with `{owner-address}` matching the bound port will be authorized to send IBC packets over channels created with `ics27-1-{connection-number}-{counterparty-connection-number}-{owner-address}`. The host chain trusts that each controller chain will enforce this port registration and access. The controller and host chain should keep track of an `active-channel` for each registered interchain account. The `active-channel` is set during the channel creation handshake process. If a channel closes, the `active-channel` should be unset. A new channel can be opened with the same source port, allowing access to the interchain account on the host chain. @@ -81,7 +81,7 @@ interface InterchainAccountModule { #### Sending Interface -The `initInterchainAccount` method in the `InterchainAccountModule` interface defines how the controller chain requests the creation of an interchain account on a host chain. Calling `initInterchainAccount` binds a new port with id `ics27-1-{connection-number}-{owner-address}` and calls `OpenChanInit` via the IBC module which will initiate the handshake process and emit an event signaling to a relayer to create a new channel between both chains. The host 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 is successful the handshake-originating (controller) chain can assume the account registration is successful. +The `initInterchainAccount` method in the `InterchainAccountModule` interface defines how the controller chain requests the creation of an interchain account on a host chain. Calling `initInterchainAccount` binds a new port with id `ics27-1-{connection-number}-{counterparty-connection-number}-{owner-address}` and calls `OpenChanInit` via the IBC module which will initiate the handshake process and emit an event signaling to a relayer to create a new channel between both chains. The host 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 is successful the handshake-originating (controller) chain can assume the account registration is successful. The `trySendTx` method in the`InterchainAccountModule` creates an outgoing IBC packet containing tx bytes (e.g. cosmos SDK messages) that a specific interchain account should execute. @@ -90,7 +90,7 @@ The `trySendTx` method in the`InterchainAccountModule` creates an outgoing IBC p `createInterchainAccount` A newly created interchain account must not conflict with an existing account. `createInterchainAccount` 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). -`executeTx` executes a transaction based on the IBC packet received from the controller chain. +`executeTx` executes a transaction based on the IBC packet received from the controller chain. `executeTx` should also check that the transaction signer is the interchain account address associated with the controller chain port-id. ### Packet Data `InterchainAccountPacketData` contains an array of messages that an interchain account can execute and a memo string that is sent to the host chain. @@ -124,7 +124,7 @@ interface InterchainAccountHook { ### Port & channel setup -The interchain account module on a host chain must always bind to a port with the id `interchain_account`. Controller chains will bind to ports dynamically, with each port id set as `ics27-1-{connection-id}-{owner-address}`. +The interchain account module on a host chain must always bind to a port with the id `interchain_account`. Controller chains will bind to ports dynamically, with each port id set as `ics27-1-{connection-number}-{counterparty-connection-number}-{owner-address}`. 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. @@ -304,3 +304,4 @@ April 27, 2021 - Redesign of ics27 specification All content herein is licensed under [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0). + From 1ea9888695a60799114e65d15337574a7026b86f Mon Sep 17 00:00:00 2001 From: Sean King Date: Fri, 16 Jul 2021 15:42:35 +0200 Subject: [PATCH 19/23] adding getInterchainAccount to onRecvPacket --- spec/app/ics-027-interchain-accounts/README.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/spec/app/ics-027-interchain-accounts/README.md b/spec/app/ics-027-interchain-accounts/README.md index af77b8568..4aa237350 100644 --- a/spec/app/ics-027-interchain-accounts/README.md +++ b/spec/app/ics-027-interchain-accounts/README.md @@ -241,10 +241,14 @@ function onRecvPacket(packet: Packet) { InterchainAccountPacketData data = packet.data const tx = deserialiseTx(packet.data.txBytes) try { - const result = executeTx(tx) - + executeTx(tx) + + // Gets the interchain account address, and returns it to the controller chain + // This step is necessary in order for the controller chain to know the address of the registered interchain account + // We should only return the interchain account on packet sequence 1 + const interchainAccount = getInterchainAccount(ctx, SourcePortId) return Acknowledgement{ - result: result + result: interchainAccount } } catch (e) { // Return ack with error. From 4ab0b0264ae128a4b5fbb977666ce16c90f39102 Mon Sep 17 00:00:00 2001 From: Sean King Date: Mon, 2 Aug 2021 18:28:17 +0200 Subject: [PATCH 20/23] Updating interface + adding flows section --- .../app/ics-027-interchain-accounts/README.md | 154 ++++++++++++++---- 1 file changed, 122 insertions(+), 32 deletions(-) diff --git a/spec/app/ics-027-interchain-accounts/README.md b/spec/app/ics-027-interchain-accounts/README.md index 4aa237350..f5e9386ee 100644 --- a/spec/app/ics-027-interchain-accounts/README.md +++ b/spec/app/ics-027-interchain-accounts/README.md @@ -20,10 +20,10 @@ On Ethereum, there are two types of accounts: externally owned accounts, control ### Definitions -- Interchain Account: 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 will send IBC packets to the host chain which signal what transactions the interchain account should execute -- Interchain Account Owner: An account on the controller chain. Every interchain account on a host chain has a respective owner account on the controller chain -- Controller Chain: The chain registering and controlling an account on a host chain. The controller chain sends IBC packets to the host chain to control the account -- 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) that the interchain account will execute +- `Interchain Account`: 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 will send IBC packets to the host chain which signal what transactions the interchain account should execute +- `Interchain Account Owner`: An account on the controller chain. Every interchain account on a host chain has a respective owner account on the controller chain +- `Controller Chain`: The chain registering and controlling an account on a host chain. The controller chain sends IBC packets to the host chain to control the account +- `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) that the interchain account will execute 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. @@ -37,16 +37,95 @@ The IBC handler interface & IBC relayer module interface are as defined in [ICS ## Technical Specification -A chain can implement one or both parts of the interchain accounts protocol (controlling and hosting). A controller chain that registers accounts on other host chains (that support interchain accounts) does not necessarily have to allow other controller chains to register accounts on its chain, and vice versa. +### General Design -This specification defines the general way to register an interchain account and transfer tx bytes. The host chain is responsible for deserializing and executing the tx bytes, and the controller chain should know how the host chain will handle the tx bytes in advance (Cosmos SDK chains will deserialize using Protobuf). +A chain can implement one or both parts of the interchain accounts protocol (*controlling* and *hosting*). A controller chain that registers accounts on other host chains (that support interchain accounts) does not necessarily have to allow other controller chains to register accounts on its chain, and vice versa. -### Authentication & Authorization +This specification defines the general way to register an interchain account and transfer tx bytes to control the account. The host chain is responsible for deserializing and executing the tx bytes, and the controller chain should know how the host chain will handle the tx bytes in advance (Cosmos SDK chains will deserialize using Protobuf). -For the controller chain to register an interchain account on a host chain, first the controlling side must bind a new port to the interchain account module with the id `ics27-1-{connection-number}-{counterparty-connection-number}-{owner-address}` where `{owner-address}` is the account address of the interchain account owner & connection number is the number parsed from the connection id (e.g. `connection-1` would have a connection number of `1`). This port will be used to create channels between the controller & host chain for a specific owner/interchain account pair. Only the account with `{owner-address}` matching the bound port will be authorized to send IBC packets over channels created with `ics27-1-{connection-number}-{counterparty-connection-number}-{owner-address}`. The host chain trusts that each controller chain will enforce this port registration and access. +### Contract +```typescript + +// * CONTROLLER CHAIN * + +// InitInterchainAccount is the entry point to registering an interchain account. +// It generates a new port identifier using the owner address, connection identifiers +// The port id will look like: ics27-1-{connection-number}-{counterparty-connection-number}-{owner-address} +// and counterparty connection identifier. It will bind to the port identifier and +// call 04-channel 'ChanOpenInit'. An error is returned if the port identifier is already in use +// An `OnChannelOpenInit` event is emitted which can be picked up by an offchain process such as a relayer +function InitInterchainAccount(connectionId: string, counterPartyConnectionId: string, ownerAddress: string) returns (nil){ +} + +// TrySendTx is used to send an IBC packet containing instructions (messages) to an interchain account on a host chain for a given interchain account owner. +function TrySendTx(connectionId: string, counterPartyConnectionId: string, ownerAddress: string, messages: []bytes) returns ([]bytes, error){ + // A port id string will be generated from the connectionIds + ownerAddress. This is the port-id that the IBC packet will be sent on + // A call to GetActiveChannel() checks if there is a currently active channel for this port-id which also implies an interchain account has previously be registered + // A call to check if the channel status is OPEN (an additional, albeit slightly redundant check) + // if there are no errors CreateOutgoingPacket() is called and the IBC packet will be sent to the host chain on the active channel +} + +// This helper function is required for the controller chain to get the address of a newly registered interchain account on a host chain. +// Because the registration of an interchain account happens during the channel creation handshake, there is no way for the controller chain to know what the address of the interchain account is on the host chain in advance. +// This function sends an IBC packet to the host chain, on the owner port + active channel with the sole intention of eventually parsing the interchain account address from the Acknowledgement packet on the controller chain side. +// The OnAcknowledgePacket function on the controller chain will handle the parsing + setting the interchain account address in state. +// The controller chain builds the messages (before sending via IBC in the TrySendTx fn) that the host side will eventually execute. Therefore, the interchain account address must be known by the controller chain. +function GetInterchainAccountAddressFromAck(connectionId: string, counterPartyConnectionId: string, ownerAddress: string) returns (nil){ + // Sends a generic IBC packet to the host chain with the intention of parsing the interchain account address associated with this port/connection/channel from the Acknowledgement packet. +} + +// * HOST CHAIN * + +// RegisterInterchainAccount is called on the OnOpenTry step during the channel creation handshake +function RegisterInterchainAccount(counterPartyPortId: string) returns (error){ + // generates an address for the interchain account + // checks to make sure the account has not already been registered + // creates a new address on chain + // calls SetInterchainAccountAddress() + // returns the address of the newly created account +} + +// DeserializeTx is used to deserialize message bytes parsed from an IBC packet into a format that the host chain can recognize & execute i.e. cosmos SDK messages +function DeserializeTx(txBytes []byte) returns ([]Any, error){ +} + +// AuthenticateTx is called before ExecuteTx. +// AuthenticateTx checks that the signer of a particular message is the interchain account associated with the counteryParty portId of the channel that the IBC packet was sent on. +function AuthenticateTx(msgs []Any, portId string) error { + // GetInterchainAccountAddress(portId) + // interchainAccountAddress != signer.String() return error +} + +// Executes each message sent by the owner on the Controller chain +function ExecuteTx(sourcePort: string, destPort: string, destChannel: string, msgs []Any) error { + // validates each message + // executes each message +} + +// * UTILITY FUNCTIONS * + +// Sets the active channel +function SetActiveChannel(portId: string, channelId: string) returns (error){ +} + +// Returns the id of the active channel if present +function GetActiveChannel(portId: string) returns (string, boolean){ +} + +// Stores the address of the interchain account in state +function SetInterchainAccountAddress(portId string, address string) returns (string) { +} -The controller and host chain should keep track of an `active-channel` for each registered interchain account. The `active-channel` is set during the channel creation handshake process. If a channel closes, the `active-channel` should be unset. A new channel can be opened with the same source port, allowing access to the interchain account on the host chain. +// Gets the interchain account from state +function GetInterchainAccountAddress(portId string) returns (string, error){ +} +``` + +### Registering & Controlling flows +**Active Channels** + +The controller and host chain should keep track of an `active-channel` for each registered interchain account. The `active-channel` is set during the channel creation handshake process. If a channel closes, the `active-channel` should be unset. A new channel can be opened with the same source port, allowing access to the interchain account on the host chain. This is a safety mechanism that allows a controller chain to regain access to an interchain account on a host chain in case of a channel closing. An active channel can look like this: @@ -62,35 +141,44 @@ An active channel can look like this: } ``` -### Data Structures +**Register Account Flow** -```typescript -interface InterchainAccountModule { - // Controlling side - initInterchainAccount(owner: string) // binds a new port with id `ics27-1-{owner-address}` - trySendTx(owner: string, data: any, connectionId: string) // sends an IBC packet containing tx bytes over the active channel for the respective owner - // Host side - createInterchainAccount(): Address - deserialiseTx(txBytes: Uint8Array): Tx - authenticateTx(messages: []sdk.Message, portId: string): Error - executeTx(tx: Tx): Result -} +To register an interchain account we require an off-chain process (relayer) to listen for `OnChannelOpenInit` events with the capability to finish a channel creation handshake on a given connection. + +1. The controller chain binds a new IBC port with an id composed of the *source/counterparty connection-ids* & the *interchain account owner address* + +The IBC portID will look like this: ``` +ics27-1-{connection-number}-{counterparty-connection-number}-{owner-address} +``` +This port will be used to create channels between the controller & host chain for a specific owner/interchain account pair. Only the account with `{owner-address}` matching the bound port will be authorized to send IBC packets over channels created with `ics27-1-{connection-number}-{counterparty-connection-number}-{owner-address}`. The host chain trusts that each controller chain will enforce this port registration and access. -**A chain can implement the entire interface, or decide to implement only the sending or receiving parts of the protocol.** +2. The controller chain emits an event signaling to open a new channel on this port given a connection +3. A relayer listening for `OnChannelOpenInit` events will begin the channel creation handshake +4. During the `OnChanOpenTry` callback on the host chain an interchain account will be registered and a mapping of the interchain account address to the owner account address will be stored in state (this is used for authenticating transactions on the host chain at execution time) +5. During the `OnChanOpenAck` & `OnChanOpenConfirm` callbacks on the controller & host chains respectively, the `active-channel` for this interchain account/owner pair, is set in state -#### Sending Interface -The `initInterchainAccount` method in the `InterchainAccountModule` interface defines how the controller chain requests the creation of an interchain account on a host chain. Calling `initInterchainAccount` binds a new port with id `ics27-1-{connection-number}-{counterparty-connection-number}-{owner-address}` and calls `OpenChanInit` via the IBC module which will initiate the handshake process and emit an event signaling to a relayer to create a new channel between both chains. The host 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 is successful the handshake-originating (controller) chain can assume the account registration is successful. +**Controlling Flow** +Once an interchain account is registered on the host chain a controller chain can begin sending instructions (messages) to control this account. -The `trySendTx` method in the`InterchainAccountModule` creates an outgoing IBC packet containing tx bytes (e.g. cosmos SDK messages) that a specific interchain account should execute. +1. The controlling chain calls `GetInterchainAccountAddressFromAck()` to get the address of the interchain account on the host chain and sets the address in state mapped to the respective portID. +2. The interchain account owner on the controller chain calls `TrySendTx` and passes message(s) that will be executed on the host side by the associated interchain account -#### Recieving Interfacce +Cosmos SDK psuedo code example: + +```typescript +interchainAccountAddress := GetInterchainAccountAddress(portId) +msg := &banktypes.MsgSend{FromAddress: interchainAccountAddress, ToAddress: ToAddress, Amount: amount} +// Sends the message to the host chain, where it will eventually be executed +TrySendTx(ownerAddress, connectionId, counterPartyConnectionId, msg) +``` + +4. The host chain upon receiving the IBC packet will call `DeserializeTx` and then call `AuthenticateTx` for each message. If either of these steps fails an error will be returned. +5. The host chain will then call `ExecuteTx` for each message and return a successful acknowledgment. -`createInterchainAccount` A newly created interchain account must not conflict with an existing account. `createInterchainAccount` 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). -`executeTx` executes a transaction based on the IBC packet received from the controller chain. `executeTx` should also check that the transaction signer is the interchain account address associated with the controller chain port-id. ### Packet Data `InterchainAccountPacketData` contains an array of messages that an interchain account can execute and a memo string that is sent to the host chain. @@ -167,7 +255,7 @@ function onChanOpenInit( // only ordered channels allowed abortTransactionUnless(order === ORDERED) // only allow channels to "interchain_account" port on counterparty chain - abortTransactionUnless(counterpartyPortIdentifier === "interchain_account") + abortTransactionUnless(counterpartyPortIdentifier === "interchain-account") // version not used at present abortTransactionUnless(version === "ics27-1") // Only open the channel if there is no active channel already set (with status OPEN) @@ -246,9 +334,9 @@ function onRecvPacket(packet: Packet) { // Gets the interchain account address, and returns it to the controller chain // This step is necessary in order for the controller chain to know the address of the registered interchain account // We should only return the interchain account on packet sequence 1 - const interchainAccount = getInterchainAccount(ctx, SourcePortId) + const interchainAccountAddress = GetInterchainAccountAddress(ctx, SourcePortId) return Acknowledgement{ - result: interchainAccount + result: interchainAccountAddress } } catch (e) { // Return ack with error. @@ -267,7 +355,8 @@ function onAcknowledgePacket( if (acknowledgement.result) { onTxSucceeded(packet.sourcePort, packet.sourceChannel, packet.data.data) // Sets the interchainAccount address on the controller side for a given owner - setInterchainAccountAddress(sourcePort, result) + // This should only be done on packet sequence 1 + setInterchainAccountAddress(sourcePort, acknowledgement.result) } else { onTxFailed(packet.sourcePort, packet.sourceChannel, packet.data.data) } @@ -309,3 +398,4 @@ All content herein is licensed under [Apache 2.0](https://www.apache.org/license + From 6a5fdbeff48c3f910659d7331df8893d54ac4fdf Mon Sep 17 00:00:00 2001 From: Sean King Date: Tue, 3 Aug 2021 12:45:42 +0200 Subject: [PATCH 21/23] fix acknowledgements/recv packet + remove channel closing --- .../app/ics-027-interchain-accounts/README.md | 65 ++++++++++++------- 1 file changed, 40 insertions(+), 25 deletions(-) diff --git a/spec/app/ics-027-interchain-accounts/README.md b/spec/app/ics-027-interchain-accounts/README.md index f5e9386ee..2931d91bb 100644 --- a/spec/app/ics-027-interchain-accounts/README.md +++ b/spec/app/ics-027-interchain-accounts/README.md @@ -75,6 +75,13 @@ function GetInterchainAccountAddressFromAck(connectionId: string, counterPartyCo // Sends a generic IBC packet to the host chain with the intention of parsing the interchain account address associated with this port/connection/channel from the Acknowledgement packet. } +// Opens a new channel on a particular port given a connection +// This is a helper function to open a new channel +// This is a safety function in case of a channel closing and the controller chain needs to regain access to an interchain account on the host chain +function InitChannel(portId: string, connectionId: string) returns (nil){ + // An `OnChannelOpenInit` event is emitted which can be picked up by an offchain process such as a relayer which will finish the channel opening handshake +} + // * HOST CHAIN * // RegisterInterchainAccount is called on the OnOpenTry step during the channel creation handshake @@ -125,7 +132,7 @@ function GetInterchainAccountAddress(portId string) returns (string, error){ ### Registering & Controlling flows **Active Channels** -The controller and host chain should keep track of an `active-channel` for each registered interchain account. The `active-channel` is set during the channel creation handshake process. If a channel closes, the `active-channel` should be unset. A new channel can be opened with the same source port, allowing access to the interchain account on the host chain. This is a safety mechanism that allows a controller chain to regain access to an interchain account on a host chain in case of a channel closing. +The controller and host chain should keep track of an `active-channel` for each registered interchain account. The `active-channel` is set during the channel creation handshake process. A new channel can be opened with the same source port, allowing access to the interchain account on the host chain. This is a safety mechanism that allows a controller chain to regain access to an interchain account on a host chain in case of a channel closing. An active channel can look like this: @@ -309,7 +316,8 @@ function onChanOpenConfirm( function onChanCloseInit( portIdentifier: Identifier, channelIdentifier: Identifier) { - unsetActiveChannel(CounterPartyPortId) + // users should not be able to close channels + return nil } ``` @@ -317,7 +325,8 @@ function onChanCloseInit( function onChanCloseConfirm( portIdentifier: Identifier, channelIdentifier: Identifier) { - unsetActiveChannel(SourcePort) + // users should not be able to close channels + return nil } ``` @@ -325,24 +334,28 @@ function onChanCloseConfirm( `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) - try { - executeTx(tx) - - // Gets the interchain account address, and returns it to the controller chain - // This step is necessary in order for the controller chain to know the address of the registered interchain account - // We should only return the interchain account on packet sequence 1 - const interchainAccountAddress = GetInterchainAccountAddress(ctx, SourcePortId) - return Acknowledgement{ - result: interchainAccountAddress - } - } catch (e) { - // Return ack with error. - return Acknowledgement{ - error: e.message, +function OnRecvPacket( + packet channeltypes.Packet, +) { + ack = channeltypes.NewResultAcknowledgement([]byte{byte(1)}) + + var data types.IBCAccountPacketData + if err = UnmarshalJSON(packet.GetData(), &data); err != nil { + ack = channeltypes.NewErrorAcknowledgement(fmt.Sprintf("cannot unmarshal ICS-27 interchain account packet data: %s", err.Error())) + } + + // only attempt the application logic if the packet data + // was successfully decoded + if ack.Success() { + err = am.keeper.OnRecvPacket(ctx, packet) + if err != nil { + ack = channeltypes.NewErrorAcknowledgement(err.Error()) + } } + + // NOTE: acknowledgement will be written synchronously during IBC handler execution. + ack = channeltypes.NewResultAcknowledgement([]byte{byte(interchainAccountAddress)}) + return ack } ``` @@ -354,9 +367,12 @@ function onAcknowledgePacket( acknowledgement: bytes) { if (acknowledgement.result) { onTxSucceeded(packet.sourcePort, packet.sourceChannel, packet.data.data) - // Sets the interchainAccount address on the controller side for a given owner - // This should only be done on packet sequence 1 - setInterchainAccountAddress(sourcePort, acknowledgement.result) + + // if the interchain account address has not been set, parse from the ack result and set in state + found = getInterchainAccountAddress(packet.sourcePort) + if(!found){ + setInterchainAccountAddress(sourcePort, String(acknowledgement.result)) + } } else { onTxFailed(packet.sourcePort, packet.sourceChannel, packet.data.data) } @@ -367,8 +383,6 @@ function onAcknowledgePacket( ```typescript function onTimeoutPacket(packet: Packet) { // Receiving chain should handle this event as if the tx in packet has failed - switch (ack.type) { - case Type.RUNTX: onTxFailed(packet.sourcePort, packet.sourceChannel, packet.data.data) return } @@ -399,3 +413,4 @@ All content herein is licensed under [Apache 2.0](https://www.apache.org/license + From f2b005d18d4b52b2c411ca4b3dc931d3615e6c62 Mon Sep 17 00:00:00 2001 From: Sean King Date: Tue, 3 Aug 2021 17:33:53 +0200 Subject: [PATCH 22/23] fix: add interchain account address to ack on packet sequence 1 --- spec/app/ics-027-interchain-accounts/README.md | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/spec/app/ics-027-interchain-accounts/README.md b/spec/app/ics-027-interchain-accounts/README.md index 2931d91bb..96fae4c36 100644 --- a/spec/app/ics-027-interchain-accounts/README.md +++ b/spec/app/ics-027-interchain-accounts/README.md @@ -351,10 +351,14 @@ function OnRecvPacket( if err != nil { ack = channeltypes.NewErrorAcknowledgement(err.Error()) } + // If the packet sequence is 1 add the interchain account address to the + if packet.Seqeunce = 1 { + var interchainAccountAddress = GetInterchainAccountAddress(packet.CounterPartyPortId) + ack = channeltypes.NewResultAcknowledgement([]byte{byte(interchainAccountAddress)}) + } } // NOTE: acknowledgement will be written synchronously during IBC handler execution. - ack = channeltypes.NewResultAcknowledgement([]byte{byte(interchainAccountAddress)}) return ack } ``` @@ -367,12 +371,10 @@ function onAcknowledgePacket( acknowledgement: bytes) { if (acknowledgement.result) { onTxSucceeded(packet.sourcePort, packet.sourceChannel, packet.data.data) - - // if the interchain account address has not been set, parse from the ack result and set in state - found = getInterchainAccountAddress(packet.sourcePort) - if(!found){ - setInterchainAccountAddress(sourcePort, String(acknowledgement.result)) - } + // If the packet sequence is 1 set the interchain account address in state + if packet.Sequence == 1 { + setInterchainAccountAddress(sourcePort, String(acknowledgement.result)) + } } else { onTxFailed(packet.sourcePort, packet.sourceChannel, packet.data.data) } @@ -414,3 +416,4 @@ All content herein is licensed under [Apache 2.0](https://www.apache.org/license + From 73e1532e4c85b4ff4ab0c5bdf827acd469c9f47e Mon Sep 17 00:00:00 2001 From: Sean King Date: Fri, 6 Aug 2021 10:53:15 +0200 Subject: [PATCH 23/23] minor fixes --- spec/app/ics-027-interchain-accounts/README.md | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/spec/app/ics-027-interchain-accounts/README.md b/spec/app/ics-027-interchain-accounts/README.md index 96fae4c36..14c3299ee 100644 --- a/spec/app/ics-027-interchain-accounts/README.md +++ b/spec/app/ics-027-interchain-accounts/README.md @@ -132,7 +132,7 @@ function GetInterchainAccountAddress(portId string) returns (string, error){ ### Registering & Controlling flows **Active Channels** -The controller and host chain should keep track of an `active-channel` for each registered interchain account. The `active-channel` is set during the channel creation handshake process. A new channel can be opened with the same source port, allowing access to the interchain account on the host chain. This is a safety mechanism that allows a controller chain to regain access to an interchain account on a host chain in case of a channel closing. +The controller and host chain should keep track of an `active-channel` for each registered interchain account. The `active-channel` is set during the channel creation handshake process. This is a safety mechanism that allows a controller chain to regain access to an interchain account on a host chain in case of a channel closing. An active channel can look like this: @@ -140,7 +140,7 @@ An active channel can look like this: ```typescript { // Controller Chain - SourcePortId: `ics-27-1-cosmos1mjk79fjjgpplak5wq838w0yd982gzkyfrk07am`, + SourcePortId: `ics-27-0-0-cosmos1mjk79fjjgpplak5wq838w0yd982gzkyfrk07am`, SourceChannelId: `channel-1`, // Host Chain CounterPartyPortId: `interchain_account`, @@ -170,8 +170,8 @@ This port will be used to create channels between the controller & host chain fo Once an interchain account is registered on the host chain a controller chain can begin sending instructions (messages) to control this account. -1. The controlling chain calls `GetInterchainAccountAddressFromAck()` to get the address of the interchain account on the host chain and sets the address in state mapped to the respective portID. -2. The interchain account owner on the controller chain calls `TrySendTx` and passes message(s) that will be executed on the host side by the associated interchain account +1. The controller chain calls `GetInterchainAccountAddressFromAck()` to get the address of the interchain account on the host chain and sets the address in state mapped to the respective portID. +2. The controller chain calls `TrySendTx` and passes message(s) that will be executed on the host side by the associated interchain account (determined by the source port identifer) Cosmos SDK psuedo code example: @@ -183,7 +183,7 @@ TrySendTx(ownerAddress, connectionId, counterPartyConnectionId, msg) ``` 4. The host chain upon receiving the IBC packet will call `DeserializeTx` and then call `AuthenticateTx` for each message. If either of these steps fails an error will be returned. -5. The host chain will then call `ExecuteTx` for each message and return a successful acknowledgment. +5. The host chain will then call `ExecuteTx` for each message and return an acknowledgment @@ -219,7 +219,7 @@ interface InterchainAccountHook { ### Port & channel setup -The interchain account module on a host chain must always bind to a port with the id `interchain_account`. Controller chains will bind to ports dynamically, with each port id set as `ics27-1-{connection-number}-{counterparty-connection-number}-{owner-address}`. +The interchain account module on a host chain must always bind to a port with the id `interchain-account`. Controller chains will bind to ports dynamically, with each port id set as `ics27-1-{connection-number}-{counterparty-connection-number}-{owner-address}`. 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. @@ -411,9 +411,3 @@ April 27, 2021 - Redesign of ics27 specification ## Copyright All content herein is licensed under [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0). - - - - - -