ConsensusState 接口的文档中所述,ClientMessage 是一个用于更新 IBC 客户端的接口。此类更新可以通过以下方式执行:
- 单个头部,
- 一批头部,
- 作恶证据,
- 或任何一种在验证后会导致 IBC 客户端共识状态发生变化的类型。
实现 ClientMessage 接口
在 modules/core/exported 中找到 ClientMessage 接口:
ClientMessage 会被传递给客户端,并在 UpdateClient 中使用。该函数会根据客户端类型获取 LightClientModule(客户端类型由 MsgUpdateClient 中可用的客户端 ID 解析得到)。这个 LightClientModule 会针对其特定的共识类型(例如 Tendermint)实现 LightClientModule 接口。
随后,UpdateClient 会处理多种情况,包括作恶行为和/或共识状态更新,并使用相关 LightClientModule 中定义的特定方法。
处理更新与作恶行为
用于处理轻客户端更新和作恶证据的函数都定义在LightClientModule 接口中,下面会分别说明。
需要特别注意的是,此处语境中的 Misbehaviour 指的是链级别、意图欺骗轻客户端的作恶行为。其具体定义由每种轻客户端自行决定。
VerifyClientMessage
VerifyClientMessage 必须验证一个 ClientMessage。ClientMessage 可以是 Header、Misbehaviour,也可以是批量更新。若要了解如何实现 ClientMessage,请参阅实现 ClientMessage 接口一节。
它必须对每一种 ClientMessage 类型进行适当处理。CheckForMisbehaviour、UpdateState 和 UpdateStateOnMisbehaviour 都会假定 ClientMessage 的内容已经通过验证并且可信。如果 ClientMessage 验证失败,则应返回错误。
关于 VerifyClientMessage 的实现示例,请参阅 Tendermint 轻客户端。
CheckForMisbehaviour
检查 Header 或 Misbehaviour 类型中是否存在作恶证据。它假定 ClientMessage 已经完成验证。
关于 CheckForMisbehaviour 的实现示例,请参阅 Tendermint 轻客户端。
Tendermint 轻客户端将Misbehaviour定义为两类不同情况:其一,在同一个信任期内,提交了两个处于相同高度但彼此冲突的Header,用于更新某个客户端的ConsensusState;其二,这两个彼此冲突的Header在不同高度被提交,但对应的共识状态并不满足正确的单调时间顺序(BFT 时间违规)。更明确地说,更新到一个新高度时,其时间戳必须大于前一个共识状态;或者,如果是在过去的高度插入一个共识状态,那么它的时间必须小于其后高度的时间,并且大于其前高度的时间。
UpdateStateOnMisbehaviour
UpdateStateOnMisbehaviour 应当在检测并验证到作恶行为后,对客户端状态执行适当的状态变更。该方法只应在已检测到作恶行为时调用,因为它本身不会执行任何作恶检查。尤其是,它应冻结客户端,以便对关联客户端状态调用 Status 函数时不再返回 Active。
关于 UpdateStateOnMisbehaviour 的实现示例,请参阅 Tendermint 轻客户端。
UpdateState
UpdateState 会按需更新并存储与 IBC 客户端关联的各类信息,例如 ClientState 及其对应的 ConsensusState。对于重复更新,它应执行 no-op。
它假定 ClientMessage 已经完成验证。
关于 UpdateState 的实现示例,请参阅 Tendermint 轻客户端。
串联整体流程
ibc-go 中的02-client Keeper 模块提供了一个参考,展示这些函数将如何被用来更新客户端。
As mentioned before in the documentation about implementing the
ConsensusState interface, ClientMessage is an interface used to update an IBC client. This update may be performed by:
- a single header,
- a batch of headers,
- evidence of misbehaviour,
- or any type which when verified produces a change to the consensus state of the IBC client.
Implementing the ClientMessage interface
Find the ClientMessage interface in modules/core/exported:
ClientMessage will be passed to the client to be used in UpdateClient, which retrieves the LightClientModule by client type (parsed from the client ID available in MsgUpdateClient). This LightClientModule implements the LightClientModule interface for its specific consenus type (e.g. Tendermint).
UpdateClient will then handle a number of cases including misbehaviour and/or updating the consensus state, utilizing the specific methods defined in the relevant LightClientModule.
Handling updates and misbehaviour
The functions for handling updates to a light client and evidence of misbehaviour are all found in theLightClientModule interface, and will be discussed below.
It is important to note that Misbehaviour in this particular context is referring to misbehaviour on the chain level intended to fool the light client. This will be defined by each light client.
VerifyClientMessage
VerifyClientMessage must verify a ClientMessage. A ClientMessage could be a Header, Misbehaviour, or batch update. To understand how to implement a ClientMessage, please refer to the Implementing the ClientMessage interface section.
It must handle each type of ClientMessage appropriately. Calls to CheckForMisbehaviour, UpdateState, and UpdateStateOnMisbehaviour will assume that the content of the ClientMessage has been verified and can be trusted. An error should be returned if the ClientMessage fails to verify.
For an example of a VerifyClientMessage implementation, please check the Tendermint light client.
CheckForMisbehaviour
Checks for evidence of a misbehaviour in Header or Misbehaviour type. It assumes the ClientMessage has already been verified.
For an example of a CheckForMisbehaviour implementation, please check the Tendermint light client.
The Tendermint light client definesMisbehaviouras two different types of situations: a situation where two conflictingHeaders with the same height have been submitted to update a client’sConsensusStatewithin the same trusting period, or that the two conflictingHeaders have been submitted at different heights but the consensus states are not in the correct monotonic time ordering (BFT time violation). More explicitly, updating to a new height must have a timestamp greater than the previous consensus state, or, if inserting a consensus at a past height, then time must be less than those heights which come after and greater than heights which come before.
UpdateStateOnMisbehaviour
UpdateStateOnMisbehaviour should perform appropriate state changes on a client state given that misbehaviour has been detected and verified. This method should only be called when misbehaviour is detected, as it does not perform any misbehaviour checks. Notably, it should freeze the client so that calling the Status function on the associated client state no longer returns Active.
For an example of a UpdateStateOnMisbehaviour implementation, please check the Tendermint light client.
UpdateState
UpdateState updates and stores as necessary any associated information for an IBC client, such as the ClientState and corresponding ConsensusState. It should perform a no-op on duplicate updates.
It assumes the ClientMessage has already been verified.
For an example of a UpdateState implementation, please check the Tendermint light client.
Putting it all together
The02-client Keeper module in ibc-go offers a reference as to how these functions will be used to update the client.