-
Notifications
You must be signed in to change notification settings - Fork 39
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
a9767d8
commit 1304a23
Showing
3 changed files
with
260 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,254 @@ | ||
--- | ||
title: "Union IBC" | ||
sidebar: | ||
badge: | ||
text: live | ||
variant: note | ||
--- | ||
|
||
import Mermaid from "#/components/Mermaid.astro"; | ||
|
||
# Overview | ||
|
||
[`IBC`](https://ibcprotocol.org) is a blockchain interoperability protocol for secure general message passing between blockchains. At Union, we use a specialized in-house version (more EVM friendly) that slightly deviates from the _canonical_ [ibc-go](https://github.com/cosmos/ibc-go) and [ibc](https://github.com/cosmos/ibc). This document is an attempt at specifying the implementation. | ||
|
||
The semantic of the core protocol can be found in the [ibc](https://github.com/cosmos/ibc/tree/41a8caa54d8691b7fa98795d31f401e1df31e18c/spec/core) repository. Our implementation is deviating from the semantic in few places that we will describe. Most of the changes are specializations/optimizations targeting the EVM. | ||
|
||
The protocol assumes the execution happens within a smart contract engine (contract addresses **MUST** be unique). | ||
|
||
## ICS-002 Client | ||
|
||
:::note | ||
|
||
[Read more on the canonical specification](https://github.com/cosmos/ibc/tree/41a8caa54d8691b7fa98795d31f401e1df31e18c/spec/core/ics-002-client-semantics) | ||
|
||
::: | ||
|
||
- [`verifyMembership`](https://github.com/cosmos/ibc/tree/41a8caa54d8691b7fa98795d31f401e1df31e18c/spec/core/ics-002-client-semantics#state-verification) no longer takes a `delayPeriodTime` and `delayPeriodBlocks`, the specific light clients SHOULD implement such verification if necessary. | ||
- [`verifyNonMembership`](https://github.com/cosmos/ibc/tree/41a8caa54d8691b7fa98795d31f401e1df31e18c/spec/core/ics-002-client-semantics#state-verification) | ||
- `delayPeriodTime` has been removed. | ||
- `delayPeriodBlocks` has been removed. | ||
- [`clientIdentifier`](https://github.com/cosmos/ibc/tree/41a8caa54d8691b7fa98795d31f401e1df31e18c/spec/core/ics-002-client-semantics#identifier-validation) is a unique `uint32`. The client type **MUST** be stored and indexable with the `clientIdentifier` see. | ||
|
||
### Additions | ||
|
||
- `registerClient` **MUST** be implemented and called before being able to call `createClient` on a light client. Only one client type **MUST** exist for a given light client: | ||
```haskell | ||
registerClient ∷ ClientType → Address → IO () | ||
registerClient clientType lightClient = do | ||
assert (getImplementation clientType ≡ null) | ||
setImplementation clientType lightClient | ||
``` | ||
|
||
## ICS-003 Connection | ||
|
||
:::note | ||
|
||
[Read more on the canonical specification](https://github.com/cosmos/ibc/blob/41a8caa54d8691b7fa98795d31f401e1df31e18c/spec/core/ics-003-connection-semantics/README.md). | ||
|
||
::: | ||
|
||
:::caution | ||
|
||
The protocol version is considered hardcoded. We support the `Ordered` and `Unordered` features for channels only. | ||
|
||
::: | ||
|
||
- [`connectionIdentifier`](https://github.com/cosmos/ibc/tree/41a8caa54d8691b7fa98795d31f401e1df31e18c/spec/core/ics-003-connection-semantics#identifier-validation) is no longer a string but a unique `uint32`. | ||
- [`ConnectionEnd`](https://github.com/cosmos/ibc/tree/41a8caa54d8691b7fa98795d31f401e1df31e18c/spec/core/ics-003-connection-semantics#data-structures) | ||
- `counterpartyPrefix` has been removed. | ||
- `version` has been removed. | ||
- `delayPeriodTime` has been removed. | ||
- `delayPeriodBlocks` has been removed. | ||
```haskell | ||
type ClientIdentifier = Uint32 | ||
type ConnectionIdentifier = Uint32 | ||
|
||
class ConnectionEnd where | ||
state ∷ ConnectionState | ||
counterpartyConnectionIdentifier ∷ ConnectionIdentifier | ||
clientIdentifier ∷ ClientIdentifier | ||
counterpartyClientIdentifier ∷ ClientIdentifier | ||
``` | ||
|
||
|
||
## ICS-004 Channel and Packet | ||
|
||
:::note | ||
|
||
[Read more on the canonical specification](https://github.com/cosmos/ibc/blob/41a8caa54d8691b7fa98795d31f401e1df31e18c/spec/core/ics-004-channel-and-packet-semantics/README.md) | ||
|
||
::: | ||
|
||
### Channel | ||
|
||
:::caution | ||
|
||
We do not support the [Channel Upgrade](https://github.com/cosmos/ibc/blob/41a8caa54d8691b7fa98795d31f401e1df31e18c/spec/core/ics-004-channel-and-packet-semantics/UPGRADES.md) feature. | ||
We only support `Ordered` and `Unordered` channels. | ||
|
||
::: | ||
|
||
- [`channelIdentifier`](https://github.com/cosmos/ibc/blob/41a8caa54d8691b7fa98795d31f401e1df31e18c/spec/core/ics-004-channel-and-packet-semantics/README.md#identifier-validation) is no longer a string but a unique `uint32`. | ||
- [`ChannelEnd`](https://github.com/cosmos/ibc/blob/41a8caa54d8691b7fa98795d31f401e1df31e18c/spec/core/ics-004-channel-and-packet-semantics/README.md#definitions): | ||
- `connectionHops` has been renamed to `connectionId` and it's type changed from `[connectionIdentifer]` to `connectionIdentifier`. | ||
- `upgradeSequence` has been removed. | ||
```haskell | ||
type ChannelIdentifier = Uint32 | ||
data ChannelOrder = Ordered | Unordered | ||
data ChannelState = Init | TryOpen | Open | Closed | ||
|
||
|
||
class ChannelEnd where | ||
state ∷ ChannelState | ||
ordering ∷ ChannelOrder | ||
connectionId ∷ ConnectionIdentifier | ||
counterpartyChannelId ∷ ChannelIdentifier | ||
counterpartyPortId ∷ String | ||
version ∷ String | ||
``` | ||
|
||
### Packet | ||
|
||
:::caution | ||
|
||
The [ICS-05 port allocation](https://github.com/cosmos/ibc/blob/41a8caa54d8691b7fa98795d31f401e1df31e18c/spec/core/ics-005-port-allocation/README.md) module has been removed, channel identifiers uniquely identify protocols and the implementor **MUST** ensure there is an existing indirection from `channelIdentifier -> protocolAddress`. | ||
|
||
::: | ||
|
||
- [`Packet`](https://github.com/cosmos/ibc/blob/41a8caa54d8691b7fa98795d31f401e1df31e18c/spec/core/ics-004-channel-and-packet-semantics/README.md#definitions) | ||
- `sourcePort` has been removed. | ||
- `destinationPort` has been removed. | ||
- `timeoutHeight` type has been changed from `(uint64, uint64)` to `uint64`. | ||
```haskell | ||
class Packet where | ||
sequence ∷ Uint64 | ||
sourceChannel ∷ ChannelIdentifier | ||
destinationChannel ∷ ChannelIdentifier | ||
payload ∷ [Uint8] | ||
timeoutHeight ∷ Uint64 | ||
timeoutTimestamp ∷ Uint64 | ||
``` | ||
|
||
## ICS-024 Host | ||
|
||
:::note | ||
|
||
[Read more on the canonical specification](https://github.com/cosmos/ibc/blob/41a8caa54d8691b7fa98795d31f401e1df31e18c/spec/core/ics-024-host-requirements/README.md#synopsis) | ||
|
||
::: | ||
|
||
### Path-space | ||
|
||
Union approach to the path-space is deviating from the canonical implementation. Since we no longer use string for client/connection/channel identifiers, the commitment paths are binary. | ||
|
||
```haskell | ||
type Prefix = Uint256 | ||
|
||
clientStatePrefix ∷ Prefix | ||
clientStatePrefix = 0x00 | ||
|
||
consensusStatePrefix ∷ Prefix | ||
consensusStatePrefix = 0x01 | ||
|
||
connectionsPrefix ∷ Prefix | ||
connectionsPrefix = 0x02 | ||
|
||
channelsPrefix ∷ Prefix | ||
channelsPrefix = 0x03 | ||
|
||
packetsPrefix ∷ Prefix | ||
packetsPrefix = 0x04 | ||
|
||
packetAcksPrefix ∷ Prefix | ||
packetAcksPrefix = 0x05 | ||
|
||
nextSeqSendPrefix ∷ Prefix | ||
nextSeqSendPrefix = 0x06 | ||
|
||
nextSeqRecvPrefix ∷ Prefix | ||
nextSeqRecvPrefix = 0x07 | ||
|
||
nextSeqAckPrefix ∷ Prefix | ||
nextSeqAckPrefix = 0x08 | ||
|
||
commit ∷ AbiEncode a ⇒ a → Bytes32 | ||
commit x = keccak256 (abiEncode x) | ||
|
||
clientStateKey ∷ ClientIdentifier → Bytes32 | ||
clientStateKey clientId = commit (clientStatePrefix, clientId) | ||
|
||
consensusStateKey ∷ ClientIdentifier → Uint64 → Bytes32 | ||
consensusStateKey clientId height = commit (consensusStatePrefix, clientId, height) | ||
|
||
connectionKey ∷ ConnectionIdentifier → Bytes32 | ||
connectionKey connectionId = commit (connectionsPrefix, connectionId) | ||
|
||
channelKey ∷ ChannelIdentifier → Bytes32 | ||
channelKey channelId = commit (channelsPrefix, channelId) | ||
|
||
packetKey ∷ ChannelIdentifier → Bytes32 → Bytes32 | ||
packetKey channelId packetHash = commit (packetsPrefix, channelId, packetHash) | ||
|
||
packetReceiptKey ∷ ChannelIdentifier → Bytes32 → Bytes32 | ||
packetReceiptKey channelId packetHash = commit (packetAcksPrefix, channelId, packetHash) | ||
|
||
nextSequenceSendKey ∷ ChannelIdentifier → Bytes32 | ||
nextSequenceSendKey channelId = commit (nextSeqSendPrefix, channelId) | ||
|
||
nextSequenceRecvKey ∷ ChannelIdentifier → Bytes32 | ||
nextSequenceRecvKey channelId = commit (nextSeqRecvPrefix, channelId) | ||
|
||
nextSequenceAckKey ∷ ChannelIdentifier → Bytes32 | ||
nextSequenceAckKey channelId = commit (nextSeqAckPrefix, channelId) | ||
``` | ||
|
||
|
||
## Extensions | ||
|
||
### ICS-004 Packet | ||
|
||
The `packetKey` and `packetReceiptKey` are special commitments that no longer takes a `sequence` but the whole packet hash. This allows us to extend the protocol with batching for sent packets and written acknowledgements. | ||
|
||
```haskell | ||
setCommitment ∷ Store → Bytes32 → Bytes32 → Store | ||
getCommitment ∷ Store → Bytes32 → Bytes32 | ||
|
||
commitmentMagic ∷ Bytes32 | ||
commitmentMagic = 0x0100000000000000000000000000000000000000000000000000000000000000 | ||
|
||
mergeAck ∷ Bytes32 → Bytes32 | ||
mergeAck ack = | ||
commitmentMagic | | ||
(ack & 0x00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) | ||
|
||
commitmentExist ∷ Store → Bytes32 → Packet → Bool | ||
commitmentExist store expectedCommitment packet = | ||
getCommitment store (commit packet) ≡ exceptedCommitment | ||
|
||
batchSend ∷ Store → [Packet] → Store | ||
batchSend store packets = do | ||
assert (all (commitmentExist store commitmentMagic) packets) | ||
setCommitment store (packetKey channelId (commit packets)) commitmentMagic | ||
|
||
batchAcks ∷ Store → [Packet] → [Acknowledgement] → Store | ||
batchAcks store packets acks = do | ||
assert ( | ||
all | ||
(\(ack, packet) -> commitmentExist store (mergeAck ack) packet) | ||
(zip acks packet) | ||
) | ||
setCommitment | ||
store | ||
(packetReceiptKey channelId (commit packets)) | ||
(mergeAck (commit acks)) | ||
``` | ||
|
||
|
||
:::tip | ||
|
||
The `commitmentMagic` value and `mergeAck` function are present to reuse the same slot to commit the receipt and the acknowledgement hash. This drastically lower the gas cost on EVM. | ||
|
||
Receipts are written when a packet is received. Acknowledgements when the execution of a received packet completes. Because of the asynchronous nature of the acknowledgement, we must store a receipt to avoid replay attacks. | ||
|
||
::: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters