IBC 协议不再要求各链验证:连接的底层对手方客户端必须是其共识协议的有效客户端。为了理解这些变更的动机,本文将说明为什么最初会有这项验证、它带来了哪些挑战,以及移除它会带来什么后果。

客户端验证的动机

最初在连接握手处理器中加入客户端验证,是为了确保两条链确实在与正确的对手方通信,也就是说,连接的配置是正确的,双方链确实彼此相连。这可以确保当某个通道建立在该连接之上,并且一个数据包通过该通道发送时,只有唯一的一条链能够接收该数据包。 IBC 依赖于各链本地唯一的客户端、连接和通道标识符。因此,这些标识符,以及 connection 结构和 channel 结构,本身并不能在全局唯一标识一条链。唯一能够唯一标识一条链的是它的共识。更具体地说,对于一条诚实链,(height, chainID, validatorSet) 这个元组是唯一的。验证者集合产生的头部会对该元组进行承诺。因此,如果链 A 上某个客户端的共识状态承诺了一个能够唯一标识链 B 的元组;那么链 B 就可以确认,链 A 上的这个客户端确实是它自己的客户端。因此,链 A 上任何构建在该客户端之上的连接,都是为了连接到链 B。 IBC 连接握手正是利用了这一点,以确保只有彼此直接指向对方的链才能完成连接握手。如果中继者在 ConnOpenInit 中选择了错误的对手方客户端标识符,从而错误配置了连接握手,那么在 ConnOpenAck 时,握手会失败,因为此时可以证明该对手方客户端并不是发起链的有效客户端。因此,错误配置的连接尝试会被阻止完成。当一个连接进入 OPEN 状态时,我们可以确信,只有这两条相关链彼此建立了连接。 如果没有这项检查,在极少数非常不走运的情况下,可能会出现这样一种情形:两条链彼此之间是有效连接的,同时还有第三方链由于配置错误而误以为自己连接到了某条并未反向连接它的链。关于这种情况的示例,请参见附带的示意图。在这种情况下,那两条正确连接的链之间的通信仍然满足 IBC 的正确性和完整性属性。然而,配置错误的那些链可能会将发送给其他链的消息误解为发送给自己的消息。在这种情况下,唯一受影响的连接端,是那些配置错误、且在目标对手方上并不存在对应有效连接端的连接端。要出现这种情况,不仅需要中继者出错,还需要标识符和握手消息时序上的巧合。因此,这种情况在实践中不太可能发生,其唯一影响是在错误配置的连接和通道端上处理无效消息。

客户端验证带来的问题

尽管阻止错误配置的连接尝试完成是有益的,但连接握手中的客户端验证给协议的可升级性和灵活性带来了很多问题。
  • 并非所有链都具备内省自身共识的能力,尤其是内省自身共识历史的能力;而验证对手方先前的共识状态恰恰需要这一点。
  • 显式验证对手方客户端状态和共识状态,会使得为同一种共识新增实现变得困难,因为任何新的客户端实现,其验证逻辑都必须得到你希望与之配合使用的对手方支持。因此,如果没有跨链协调,ClientState 和 ConsensusState 的结构就很难变更。
  • 同样,证明依赖于 ClientState 和 ConsensusState 的 ICS24 路径。因此,如果没有跨链协调,就很难将这些键路径改为更高效的表示方式。

社会共识

如上所述,连接握手中的客户端验证能够防止创建处于 OPEN 状态但配置错误的连接和通道。然而,它并不能阻止创建那些同样处于 OPEN 状态、但却通向恶意链的连接和通道。IBC 处理这类情况的方式,是依赖社会共识。这可以表现为显式的社会共识,例如由治理批准的客户端、连接和通道;也可以表现为隐式的社会共识,即 IBC 消息本身是无许可的,但在链外已经就哪个连接 ID 才是所有用户都会使用、用于与外部链通信的规范连接达成一致。这种链外共识可以体现在链注册表和前端中,并进一步展示给终端用户,以防止他们无意中使用错误的通道。 因此,对于终端用户而言,社会共识本来就是 IBC 运作中的关键组成部分。我们可以将这种既有的社会共识进一步扩展,用它来阻止用户通过错误配置的连接端发送消息,而不是在协议中强制执行这类验证。移除这项验证后,我们可以极大简化连接握手协议:在 ConnOpenTry 和 ConnOpenAck 中各移除两次证明验证。账本也不再需要跟踪自身共识,以显式验证对手方的客户端。这使客户端的实现方式以及写入状态的方式获得了更多自由和灵活性。 虽然移除连接握手中的客户端验证,确实会带来一种很小的可能性,即出现配置错误但仍可使用的通道,但未来将依赖社会共识来确保这些错误配置的通道不会被使用。
The IBC protocol is no longer requiring that chains verify that the underlying counterparty client of a connection is a valid client of their consensus protocol. In order to understand the motivation for these changes, this document will describe why the validation existed in the first place, what challenges they introduced, and what the consequences are of removing them.

Client Validation Motivation

Client validation was initially included in the connection handshake handlers in order to ensure that both chains were talking to the correct counterparty, i.e. the connection was correctly configured such that both chains are talking to each other. This ensures that when a channel is built on top of that connection, and a packet is sent over that channel, only a single chain is capable of receiving the packet. IBC relies on locally unique identifiers for each chain’s client, connection and channel identifiers. Thus, the identifiers, connection struct and channel struct are not unique to a chain. The only thing that uniquely identifies a chain is its consensus. Specifically, the tuple of (height, chainID, validatorSet) is unique for an honest chain. This tuple is committed to by the headers a validator set produces. Thus, if a chain A has a client with a consensus state that is committing to a tuple uniquely identifying chain B; then chain B can be sure that the client on chain A is a client of itself. Thus any connection on chain A built on top of that client is meant to connect to chain B. The IBC connection handshake used this fact to ensure that the connection handshake only completes for the chains that are directly pointing to one another. If a relayer misconfigured the connection handshake by choosing the wrong counterparty client identifer on ConnOpenInit, the handshake would fail on ConnOpenAck when the counterparty client is proven to not be a valid client of the initializing chain. Thus, misconfigured connection attempts are blocked from completing. When a connection moves to OPEN, we can be sure that only the two chains in question are connected to each other. Without this check, it is possible in very unlucky circumstances to have two chains that are validly connected to each other and also have misconfigured third-party chains that believe they are connected to a chain that is not connected back to them. For an example of this situation, see the attached diagram. In this case, the validly connected chains will have communication between them that follows IBC’s correctness and integrity properties. However, the chains that are misconfigured may misinterpret messages sent to other chains as messages intended for them. In this case, the only connection ends that are affected are the misconfigured connection ends that do not correlate to a valid connection end on the intended counterparty. In order for this situation to arise, there would need to not only be relayer error, but also a coincidence in identifiers and handshake message timing. Thus, this is an unlikely situation to arise in practice and the only effect is invalid message processing on misconfigured connections and channel ends.

Client Validation Problems

While it is beneficial that misconfigured connection attempts are blocked from completing, the client validation in the connection handshake introduced a lot of problems for the upgradability and flexibility of the protocol.
  • Not all chains have the ability to introspect their own consensus, specifically their own consensus history which is required to validate a counterparty’s previous consensus state.
  • Explicit verification of a counterparty client state and consensus state makes adding new implementions of the same consensus difficult since the validation of any new client implementations must be supported on the counterparty you want to use it with. Thus, the structure of ClientState and ConsensusState is very difficult to change without interchain coordination.
  • Similarly, the proofs rely on ICS24 paths for the ClientState and ConsensusState. Thus, changing the key paths to a more efficient representation is very difficult without interchain coordination.

Social Consensus

As mentioned above, the client validation in the connection handshake prevents the creation of OPEN misconfigured connections and channels. However, it does not prevent the creation of OPEN connections and channels that are opened to malicious chains. The way IBC handles these situations is to rely on social consensus. This can be in the form of explicit social consensus, i.e. governance approved clients, connections and channels; or implicit social consensus where IBC messages are permissionless but there exists an out-of-band consensus on which connection ID is the canonical connection that all users will use to communicate to an external chain. This out-of-band consensus can be reflected in chain registries and front ends that are reflected to end users to prevent them from unintentionally using the wrong channel. Thus, social consensus is already a key element of how IBC functions for end users. We can extend the use of this pre-existing social consensus to also prevent users from sending on misconfigured connection ends rather than enforcing validation in the protocol. By removing the validation, we vastly simplify the connection handshake protocol: removing two proof verifications in both ConnOpenTry and ConnOpenAck. Ledgers no longer need to track their own consensus in order to explicitly validate a counterparty’s client. This gives much more freedom and flexibility to how clients are implemented and written into state. While removing client validation in the connection handshake does open the slight possibility of misconfigured but still usable channels, social consensus will be relied on going forward to ensure these misconfigured channels do not get usage.