Synopsis
The routing module is a default implementation of a secondary module which will accept external datagrams and call into the interblockchain communication protocol handler to deal with handshakes and packet relay. The routing module keeps a lookup table of modules, which it can use to look up and call a module when a packet is received, so that external relayers need only ever relay packets to the routing module.Motivation
The default IBC handler uses a receiver call pattern, where modules must individually call the IBC handler in order to bind to ports, start handshakes, accept handshakes, send and receive packets, etc. This is flexible and simple but is a bit tricky to understand and may require extra work on the part of relayer processes, who must track the state of many modules. This standard describes an IBC “routing module” to automate most common functionality, route packets, and simplify the task of relayers. The routing module can also play the role of the module manager as discussed in ICS 5 and implement logic to determine when modules are allowed to bind to ports and what those ports can be named.Definitions
All functions provided by the IBC handler interface are defined as in ICS 25. The functionsnewCapability & authenticateCapability are defined as in ICS 5.
The functions writeChannel and writeAcknowledgement are defined as in ICS 4
Desired Properties
- Modules should be able to bind to ports and own channels through the routing module.
- No overhead should be added for packet sends and receives other than the layer of call indirection.
- The routing module should call specified handler functions on modules when they need to act upon packets.
Technical Specification
Note: If the host state machine is utilising object capability authentication (see ICS 005), all functions utilising ports take an additional capability parameter.
Module callback interface
Modules must expose the following function signatures to the routing module, which are called upon the receipt of various datagrams:OnChanOpenInit
onChanOpenInit will verify that the relayer-chosen parameters
are valid and perform any custom INIT logic.
It may return an error if the chosen parameters are invalid
in which case the handshake is aborted.
If the provided version string is non-empty, onChanOpenInit should return
the version string or an error if the provided version is invalid.
If the version string is empty, onChanOpenInit is expected to
return a default version string representing the version(s)
it supports.
If there is no default version string for the application,
it should return an error if provided version is empty string.
OnChanOpenTry
onChanOpenTry will verify the INIT-chosen parameters along with the
counterparty-chosen version string and perform custom TRY logic.
If the INIT-chosen parameters
are invalid, the callback must return an error to abort the handshake.
If the counterparty-chosen version is not compatible with this modules
supported versions, the callback must return an error to abort the handshake.
If the versions are compatible, the try callback must select the final version
string and return it to core IBC.
onChanOpenTry may also perform custom initialization logic
OnChanOpenAck
onChanOpenAck will error if the counterparty selected version string
is invalid to abort the handshake. It may also perform custom ACK logic.
OnChanOpenConfirm
onChanOpenConfirm will perform custom CONFIRM logic and may error to abort the handshake.
ModuleCallbacks interface:
Port binding as module manager
The IBC routing module sits in-between the handler module (ICS 25) and individual modules on the host state machine. The routing module, acting as a module manager, differentiates between two kinds of ports:- “Existing name” ports: e.g. “bank”, with standardised prior meanings, which should not be first-come-first-serve
- “Fresh name” ports: new identity (perhaps a smart contract) w/no prior relationships, new random number port, post-generation port name can be communicated over another channel
bindPort can be called by a module in order to bind to a port, through the routing module, and set up callbacks.
updatePort can be called by a module in order to alter the callbacks.
releasePort can be called by a module in order to release a port previously in use.
Warning: releasing a port will allow other modules to bind to that port and possibly intercept incoming channel opening handshakes. Modules should release ports only when doing so is safe.
lookupModule can be used by the routing module to lookup the callbacks bound to a particular port.
Datagram handlers (write)
Datagrams are external data blobs accepted as transactions by the routing module. This section defines a handler function for each datagram, which is executed when the associated datagram is submitted to the routing module in a transaction. All datagrams can also be safely submitted by other modules to the routing module. No message signatures or data validity checks are assumed beyond those which are explicitly indicated.Client lifecycle management
ClientCreate creates a new light client with the specified identifier & consensus state.
ClientUpdate updates an existing light client with the specified identifier & new header.
ClientSubmitMisbehaviour submits proof-of-misbehaviour to an existing light client with the specified identifier.
Connection lifecycle management
TheConnOpenInit datagram starts the connection handshake process with an IBC module on another chain.
ConnOpenTry datagram accepts a handshake request from an IBC module on another chain.
ConnOpenAck datagram confirms a handshake acceptance by the IBC module on another chain.
ConnOpenConfirm datagram acknowledges a handshake acknowledgement by an IBC module on another chain & finalises the connection.
Channel lifecycle management
Packet relay
Packets are sent by the module directly (by the module calling the IBC handler).Packet timeouts
Closure-by-timeout & packet cleanup
Query (read-only) functions
All query functions for clients, connections, and channels should be exposed (read-only) directly by the IBC handler module.Interface usage example
See ICS 20 for a usage example.Properties & Invariants
- Proxy port binding is first-come-first-serve: once a module binds to a port through the IBC routing module, only that module can utilise that port until the module releases it.
Backwards Compatibility
Not applicable.Forwards Compatibility
routing modules are closely tied to the IBC handler interface.Example Implementations
- Implementation of ICS 26 in Go can be found in ibc-go repository.
- Implementation of ICS 26 in Rust can be found in ibc-rs repository.