Channels
Channels provide an application-level communication protocol built on top of connections. While connections handle the basic secure transport between chains, channels implement message delivery and application-specific logic. Think of channels as dedicated message queues between specific applications on different chains, where messages are typed and have certain effects.
sequenceDiagram participant App on Chain A participant Chain A participant Chain B participant App on Chain B App on Chain A->>Chain A: Request channel creation Chain A->>Chain B: ChanOpenInit Chain B->>App on Chain B: Notify app Chain B->>Chain A: ChanOpenTry Chain A->>Chain B: ChanOpenAck Chain B->>Chain A: ChanOpenConfirm Note over Chain A,Chain B: Channel Established App on Chain A->>Chain A: Send packet Chain A->>Chain B: Packet transfer Chain B->>App on Chain B: Deliver packet
Each channel has key properties:
- Ordering: Controls packet delivery (ordered, unordered, or ordered with timeouts)
- Version: Application-specific string for protocol versioning
- State: Tracks the channel establishment process
The channel handshake ensures both applications:
- Agree on the version
- Are ready to process packets
- Can verify each other's packet commitments
Multiple channels can exist over a single connection, each serving different applications. For example, a token transfer application and a governance application could each have their own channel while sharing the underlying secure connection. In general, Union multiplexes traffic over connections and only maintains one connection per chain, while operating many different channels.
Channel Usecases
Whenever a protocol has a structured message format, it should consider using a specific channel. This is useful for indexers, which use channel.version
to read packets for further analysis.
We can query active channels by running:
gq https://development.graphql.union.build/v1/graphql -q '
query Channels @cached(ttl: 60) {
v2_channels(args: { p_limit: 30 }) {
source_universal_chain_id
source_client_id
source_connection_id
source_channel_id
source_port_id
destination_universal_chain_id
destination_client_id
destination_connection_id
destination_channel_id
destination_port_id
version
}
}
'
nix shell nixpkgs#nodePackages.graphqurl
You will probably see ucs03-zkgm-0
in the output, which is the multiplexed transfer protocol. Like a swiss-army knife, it works for loads of complex applications. Other common versions are ics20
, which is used for legacy asset transfers. With multiplexed, we mean that a single channel serves many applications at the same time.
graph TB B1[Token Bridge] & B2[NFT Bridge] & B3[Governance] --- MC[ucs03-zkgm-0] MC --- Chain3[Chain B] Chain3 --- B4[Token Bridge] & B5[NFT Bridge] & B6[Governance]
In legacy channel configurations, there would be 3 individual channels. Multiplexing offers key advantes:
- Applications do not need to relay their own channels.
- Smart contract developers can leverage enshrined smart contracts.
- The channel implementation can use smart batching to limit the amount of packets necessary.