概述
路由模块是一个次级模块的默认实现,它会接收外部数据报,并调用区块间通信协议处理器来处理握手与数据包中继。 路由模块维护一张模块查找表,当收到数据包时,它可以用这张表查找并调用相应模块,因此外部中继器只需要始终将数据包中继到路由模块。设计动机
默认的 IBC 处理器使用接收方调用模式,其中模块必须分别调用 IBC 处理器,才能绑定端口、发起握手、接受握手、发送和接收数据包等。这种方式灵活且简单,但理解起来稍有难度,并且可能会给中继进程带来额外工作,因为它们必须跟踪许多模块的状态。本标准描述了一种 IBC“路由模块”,用于自动化大多数常见功能、路由数据包,并简化中继器的任务。 路由模块也可以承担 ICS 5 中讨论的模块管理器角色,并实现 用于确定模块何时允许绑定端口以及这些端口可以如何命名的逻辑。定义
IBC 处理器接口提供的所有函数均按 ICS 25 中的定义。 函数newCapability 和 authenticateCapability 按 ICS 5 中的定义。
函数 writeChannel 和 writeAcknowledgement 按 ICS 4 中的定义。
期望属性
- 模块应能够通过路由模块绑定端口并拥有通道。
- 除了调用间接层之外,数据包发送和接收不应增加额外开销。
- 当模块需要对数据包执行操作时,路由模块应调用模块上指定的处理函数。
技术规范
注意:如果宿主状态机正在使用对象能力认证(见 ICS 005),则所有使用端口的函数都需要额外接收一个 capability 参数。
模块回调接口
模块必须向路由模块暴露以下函数签名,这些函数会在收到各种数据报时被调用:OnChanOpenInit
onChanOpenInit 将验证由中继器选择的参数
是否有效,并执行任何自定义 INIT 逻辑。
如果所选参数无效,它可以返回错误,
此时握手会被中止。
如果提供的版本字符串非空,onChanOpenInit 应返回
该版本字符串;如果提供的版本无效,则返回错误。
如果版本字符串为空,预期 onChanOpenInit
返回一个默认版本字符串,以表示
它所支持的版本。
如果该应用没有默认版本字符串,
那么在提供的版本为空字符串时,它应返回错误。
OnChanOpenTry
onChanOpenTry 将验证 INIT 阶段所选择的参数,以及
对手方选择的版本字符串,并执行自定义 TRY 逻辑。
如果 INIT 阶段选择的参数
无效,则该回调必须返回错误以中止握手。
如果对手方选择的版本与该模块
支持的版本不兼容,则该回调必须返回错误以中止握手。
如果版本兼容,则 try 回调必须选择最终的版本
字符串,并将其返回给核心 IBC。
onChanOpenTry 也可以执行自定义初始化逻辑。
OnChanOpenAck
onChanOpenAck 会在对手方选择的版本字符串
无效时抛出错误,以中止握手。它也可以执行自定义 ACK 逻辑。
OnChanOpenConfirm
onChanOpenConfirm 将执行自定义 CONFIRM 逻辑,并且可能通过报错来中止握手。
ModuleCallbacks 接口中:
作为模块管理器的端口绑定
IBC 路由模块位于处理器模块(ICS 25)与宿主状态机上的各个模块之间。 路由模块作为模块管理器,会区分两类端口:- “现有名称”端口:例如“bank”,具有标准化的既有含义,不应采用先到先得的方式
- “新名称”端口:新的身份(例如智能合约),无既有关系,新的随机数端口,生成后的端口名可以通过其他通道进行传递
bindPort,通过路由模块绑定到某个端口,并设置回调。
updatePort 来修改回调。
releasePort 来释放之前正在使用的端口。
警告:释放端口将允许其他模块绑定到该端口,并可能拦截传入的通道打开握手。模块仅应在确认安全时释放端口。
lookupModule 来查找绑定到特定端口的回调。
数据报处理器(写入)
数据报 是由路由模块作为交易接收的外部数据块。本节为每种数据报定义了一个处理函数, 当相应数据报在某笔交易中提交给路由模块时,就会执行该函数。 所有数据报也都可以由其他模块安全地提交给路由模块。 除非有明确说明,否则不假定存在任何消息签名或数据有效性检查。客户端生命周期管理
ClientCreate 使用指定的标识符和共识状态创建一个新的轻客户端。
ClientUpdate 使用指定的标识符和新的头部更新一个现有轻客户端。
ClientSubmitMisbehaviour 向指定标识符的现有轻客户端提交作恶证明。
连接生命周期管理
ConnOpenInit 数据报会与另一条链上的 IBC 模块启动连接握手流程。
ConnOpenTry 数据报会接受来自另一条链上的 IBC 模块的握手请求。
ConnOpenAck 数据报会确认另一条链上的 IBC 模块已接受握手。
ConnOpenConfirm 数据报会确认另一条链上的 IBC 模块发出的握手确认,并完成该连接。
通道生命周期管理
数据包中继
数据包由模块直接发送(即由模块调用 IBC 处理器发送)。数据包超时
基于超时的关闭与数据包清理
查询(只读)函数
客户端、连接和通道的所有查询函数都应由 IBC 处理程序模块直接暴露为只读接口。接口使用示例
用法示例见 ICS 20。属性与不变量
- 代理端口绑定遵循先到先得原则:一旦某个模块通过 IBC 路由模块绑定到某个端口,在该模块释放该端口之前,只有该模块可以使用该端口。
向后兼容性
不适用。向前兼容性
路由模块与 IBC 处理程序接口紧密耦合。实现示例
- ICS 26 的 Go 实现可在 ibc-go repository 中找到。
- ICS 26 的 Rust 实现可在 ibc-rs repository 中找到。
历史
2019 年 6 月 9 日 - 提交草案 2019 年 7 月 28 日 - 重大修订 2019 年 8 月 25 日 - 重大修订 2023 年 3 月 28 日 - 修复模块处理程序与应用回调的执行顺序版权
此处的所有内容均依据 Apache 2.0 许可发布。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.