Skip to content

Commit 8d7e891

Browse files
feat(docs): union ibc spec
1 parent a9767d8 commit 8d7e891

File tree

3 files changed

+260
-14
lines changed

3 files changed

+260
-14
lines changed

docs/astro.config.ts

+6
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,12 @@ export default defineConfig({
155155
label: "Overview",
156156
link: "/protocol/overview"
157157
},
158+
{
159+
label: "Specifications",
160+
autogenerate: {
161+
directory: "/protocol/specifications"
162+
}
163+
},
158164
{
159165
label: "Channels",
160166
autogenerate: {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
1+
---
2+
title: "Union IBC"
3+
sidebar:
4+
badge:
5+
text: live
6+
variant: note
7+
---
8+
9+
import Mermaid from "#/components/Mermaid.astro";
10+
11+
# Overview
12+
13+
[`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.
14+
15+
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.
16+
17+
The protocol assumes the execution happens within a smart contract engine (contract addresses **MUST** be unique).
18+
19+
## ICS-002 Client
20+
21+
:::note
22+
23+
[Read more on the canonical specification](https://github.com/cosmos/ibc/tree/41a8caa54d8691b7fa98795d31f401e1df31e18c/spec/core/ics-002-client-semantics)
24+
25+
:::
26+
27+
- [`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.
28+
- [`verifyNonMembership`](https://github.com/cosmos/ibc/tree/41a8caa54d8691b7fa98795d31f401e1df31e18c/spec/core/ics-002-client-semantics#state-verification)
29+
- `delayPeriodTime` has been removed.
30+
- `delayPeriodBlocks` has been removed.
31+
- [`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.
32+
33+
### Additions
34+
35+
- `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:
36+
```haskell
37+
registerClient ClientType Address IO ()
38+
registerClient clientType lightClient = do
39+
assert (getImplementation clientType null)
40+
setImplementation clientType lightClient
41+
```
42+
43+
## ICS-003 Connection
44+
45+
:::note
46+
47+
[Read more on the canonical specification](https://github.com/cosmos/ibc/blob/41a8caa54d8691b7fa98795d31f401e1df31e18c/spec/core/ics-003-connection-semantics/README.md).
48+
49+
:::
50+
51+
:::caution
52+
53+
The protocol version is considered hardcoded. We support the `Ordered` and `Unordered` features for channels only.
54+
55+
:::
56+
57+
- [`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`.
58+
- [`ConnectionEnd`](https://github.com/cosmos/ibc/tree/41a8caa54d8691b7fa98795d31f401e1df31e18c/spec/core/ics-003-connection-semantics#data-structures)
59+
- `counterpartyPrefix` has been removed.
60+
- `version` has been removed.
61+
- `delayPeriodTime` has been removed.
62+
- `delayPeriodBlocks` has been removed.
63+
```haskell
64+
type ClientIdentifier = Uint32
65+
type ConnectionIdentifier = Uint32
66+
67+
class ConnectionEnd where
68+
state ConnectionState
69+
counterpartyConnectionIdentifier ConnectionIdentifier
70+
clientIdentifier ClientIdentifier
71+
counterpartyClientIdentifier ClientIdentifier
72+
```
73+
74+
75+
## ICS-004 Channel and Packet
76+
77+
:::note
78+
79+
[Read more on the canonical specification](https://github.com/cosmos/ibc/blob/41a8caa54d8691b7fa98795d31f401e1df31e18c/spec/core/ics-004-channel-and-packet-semantics/README.md)
80+
81+
:::
82+
83+
### Channel
84+
85+
:::caution
86+
87+
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.
88+
We only support `Ordered` and `Unordered` channels.
89+
90+
:::
91+
92+
- [`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`.
93+
- [`ChannelEnd`](https://github.com/cosmos/ibc/blob/41a8caa54d8691b7fa98795d31f401e1df31e18c/spec/core/ics-004-channel-and-packet-semantics/README.md#definitions):
94+
- `connectionHops` has been renamed to `connectionId` and it's type changed from `[connectionIdentifer]` to `connectionIdentifier`.
95+
- `upgradeSequence` has been removed.
96+
```haskell
97+
type ChannelIdentifier = Uint32
98+
data ChannelOrder = Ordered | Unordered
99+
data ChannelState = Init | TryOpen | Open | Closed
100+
101+
102+
class ChannelEnd where
103+
state ChannelState
104+
ordering ChannelOrder
105+
connectionId ConnectionIdentifier
106+
counterpartyChannelId ChannelIdentifier
107+
counterpartyPortId String
108+
version String
109+
```
110+
111+
### Packet
112+
113+
:::caution
114+
115+
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`.
116+
117+
:::
118+
119+
- [`Packet`](https://github.com/cosmos/ibc/blob/41a8caa54d8691b7fa98795d31f401e1df31e18c/spec/core/ics-004-channel-and-packet-semantics/README.md#definitions)
120+
- `sourcePort` has been removed.
121+
- `destinationPort` has been removed.
122+
- `timeoutHeight` type has been changed from `(uint64, uint64)` to `uint64`.
123+
```haskell
124+
class Packet where
125+
sequence Uint64
126+
sourceChannel ChannelIdentifier
127+
destinationChannel ChannelIdentifier
128+
payload [Uint8]
129+
timeoutHeight Uint64
130+
timeoutTimestamp Uint64
131+
```
132+
133+
## ICS-024 Host
134+
135+
:::note
136+
137+
[Read more on the canonical specification](https://github.com/cosmos/ibc/blob/41a8caa54d8691b7fa98795d31f401e1df31e18c/spec/core/ics-024-host-requirements/README.md#synopsis)
138+
139+
:::
140+
141+
### Path-space
142+
143+
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.
144+
145+
```haskell
146+
type Prefix = Uint256
147+
148+
clientStatePrefix Prefix
149+
clientStatePrefix = 0x00
150+
151+
consensusStatePrefix Prefix
152+
consensusStatePrefix = 0x01
153+
154+
connectionsPrefix Prefix
155+
connectionsPrefix = 0x02
156+
157+
channelsPrefix Prefix
158+
channelsPrefix = 0x03
159+
160+
packetsPrefix Prefix
161+
packetsPrefix = 0x04
162+
163+
packetAcksPrefix Prefix
164+
packetAcksPrefix = 0x05
165+
166+
nextSeqSendPrefix Prefix
167+
nextSeqSendPrefix = 0x06
168+
169+
nextSeqRecvPrefix Prefix
170+
nextSeqRecvPrefix = 0x07
171+
172+
nextSeqAckPrefix Prefix
173+
nextSeqAckPrefix = 0x08
174+
175+
commit AbiEncode a a Bytes32
176+
commit x = keccak256 (abiEncode x)
177+
178+
clientStateKey ClientIdentifier Bytes32
179+
clientStateKey clientId = commit (clientStatePrefix, clientId)
180+
181+
consensusStateKey ClientIdentifier Uint64 Bytes32
182+
consensusStateKey clientId height = commit (consensusStatePrefix, clientId, height)
183+
184+
connectionKey ConnectionIdentifier Bytes32
185+
connectionKey connectionId = commit (connectionsPrefix, connectionId)
186+
187+
channelKey ChannelIdentifier Bytes32
188+
channelKey channelId = commit (channelsPrefix, channelId)
189+
190+
packetKey ChannelIdentifier Bytes32 Bytes32
191+
packetKey channelId packetHash = commit (packetsPrefix, channelId, packetHash)
192+
193+
packetReceiptKey ChannelIdentifier Bytes32 Bytes32
194+
packetReceiptKey channelId packetHash = commit (packetAcksPrefix, channelId, packetHash)
195+
196+
nextSequenceSendKey ChannelIdentifier Bytes32
197+
nextSequenceSendKey channelId = commit (nextSeqSendPrefix, channelId)
198+
199+
nextSequenceRecvKey ChannelIdentifier Bytes32
200+
nextSequenceRecvKey channelId = commit (nextSeqRecvPrefix, channelId)
201+
202+
nextSequenceAckKey ChannelIdentifier Bytes32
203+
nextSequenceAckKey channelId = commit (nextSeqAckPrefix, channelId)
204+
```
205+
206+
207+
## Extensions
208+
209+
### ICS-004 Packet
210+
211+
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.
212+
213+
```haskell
214+
setCommitment Store Bytes32 Bytes32 Store
215+
getCommitment Store Bytes32 Bytes32
216+
217+
commitmentMagic Bytes32
218+
commitmentMagic = 0x0100000000000000000000000000000000000000000000000000000000000000
219+
220+
mergeAck Bytes32 Bytes32
221+
mergeAck ack =
222+
commitmentMagic |
223+
(ack & 0x00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
224+
225+
commitmentExist Store Bytes32 Packet Bool
226+
commitmentExist store expectedCommitment packet =
227+
getCommitment store (commit packet) exceptedCommitment
228+
229+
batchSend Store [Packet] Store
230+
batchSend store packets = do
231+
assert (all (commitmentExist store commitmentMagic) packets)
232+
setCommitment store (packetKey channelId (commit packets)) commitmentMagic
233+
234+
batchAcks Store [Packet] [Ackowledgement] Store
235+
batchAcks store packets acks = do
236+
assert (
237+
all
238+
(\(ack, packet) -> commitmentExist store (mergeAck ack) packet)
239+
(zip acks packet)
240+
)
241+
setCommitment
242+
store
243+
(packetReceiptKey channelId (commit packets))
244+
(mergeAck (commit acks))
245+
```
246+
247+
248+
:::tip
249+
250+
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.
251+
252+
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.
253+
254+
:::

evm/contracts/core/24-host/IBCCommitment.sol

-14
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,6 @@ library IBCCommitment {
3636
return abi.encode(CHANNELS, channelId);
3737
}
3838

39-
function packetCommitmentPath(
40-
uint32 channelId,
41-
uint64 sequence
42-
) internal pure returns (bytes memory) {
43-
return abi.encode(PACKETS, channelId, sequence);
44-
}
45-
4639
function batchPacketsCommitmentPath(
4740
uint32 channelId,
4841
bytes32 batchHash
@@ -102,13 +95,6 @@ library IBCCommitment {
10295
return keccak256(channelPath(channelId));
10396
}
10497

105-
function packetCommitmentKey(
106-
uint32 channelId,
107-
uint64 sequence
108-
) internal pure returns (bytes32) {
109-
return keccak256(packetCommitmentPath(channelId, sequence));
110-
}
111-
11298
function batchPacketsCommitmentKey(
11399
uint32 channelId,
114100
bytes32 batchHash

0 commit comments

Comments
 (0)