概述
本规范文档描述了一个以 Wasm 字节码形式存储在区块链上的轻客户端接口。动机
目前,添加新的客户端实现或升级现有实现都需要进行硬升级,因为客户端实现是静态链二进制文件的一部分。任何链上轻客户端代码的变更,都依赖链治理先批准升级,然后才能部署。 当新增新的客户端类型时,这种方式或许可以接受,因为当前需要支持的独特共识算法数量仍然较少。然而,一旦涉及轻客户端升级,这个过程就会变得非常繁琐。 如果没有可动态升级的轻客户端,一个希望升级其共识算法的链(从而使现有轻客户端失效)必须等待所有对手链先执行硬升级,加入对升级后轻客户端的支持,然后它才能在自己的链上执行升级。破坏轻客户端兼容性的共识升级示例包括:从 Tendermint v1 升级到会破坏轻客户端的 Tendermint v2,或者从 Tendermint 共识切换到 Honeybadger。内部状态机逻辑的变更不会影响共识。例如,对质押模块的修改不需要 IBC 升级。 要求所有对手方都在其二进制中静态加入新的客户端实现,必然会拖慢 IBC 网络中的升级节奏,因为即使是一个非常实验性、快速演进的链,其升级部署也可能被某条高价值链的升级所阻塞,而后者天然会更加保守。 一旦 IBC 网络广泛采用可动态升级的客户端,链就可以在任何希望的时间升级其共识算法,而中继者也可以升级所有对手链的客户端代码,而不需要对手链自己执行升级。这避免了在考虑升级自身共识算法时对对手链的依赖。 该接口的另一个好处是,它消除了轻客户端与 Go 编程语言之间的依赖关系。借助 Wasm 作为编译目标,只要某种编程语言的工具链支持将代码编译为 Wasm,轻客户端就可以用该语言编写。示例包括 Go、Rust、C 和 C++。定义
函数和术语的定义见 ICS 2。currentTimestamp 的定义见 ICS 24。
Wasm VM 指能够执行有效 Wasm 字节码的虚拟机。
Wasm Contract 指存储在 Wasm VM 中的 Wasm 字节码,它提供 ICS 2 的某个目标区块链特定实现。
Wasm Client Proxy 指 ICS 8 的一种实现,它作为 Wasm 客户端的透传层。
Wasm Client 指某个特定的 Wasm Contract 实例,定义为元组 (Wasm Contract, ClientID)。
期望属性
本规范必须满足 ICS 2. 中定义的客户端接口。技术规范
本规范依赖于 Wasm 客户端被正确实例化,并且与目标blockchain 共识算法的任何具体实现解耦。
存储管理
ICS 2 中定义的轻客户端操作可以是有状态的;它们可能会修改存储中保存的状态。为此,需要允许底层 Wasm 轻客户端实现访问客户端和共识数据结构,并在执行某些计算之后,用它们的新版本更新存储。 因此,ibc-go 中的实现选择在02-client 模块(用于读取)、08-wasm 模块(用于实例化)以及 Wasm 合约之间共享 Wasm 客户端存储。除实例化之外,Wasm 合约负责更新状态。
Wasm VM
该模块的目的是将轻客户端逻辑委托给一个使用 Wasm 编写的模块。为此,Wasm 客户端代理需要持有对某个 Wasm VM 的引用(或处理器)。随后,Wasm 客户端代理可以直接调用wasmvm 与 VM 交互,相比通过 x/wasm 这类中间模块,它具有更低的开销、更少的依赖,以及对 Wasm 客户端存储更细粒度的控制。
Gas 成本
wasmd 已经对 CosmWasm 的 gas 调整 做了充分基准测试,而 ibc-go 的 ICS 8 实现所使用的 Wasm VM 采用了相同的数值。
客户端状态
Wasm 客户端状态通过checksum 跟踪 Wasm 字节码的位置。data 字段表示的二进制数据是不透明的,仅由 Wasm 合约解释。
共识状态
Wasm 共识状态跟踪 Wasm 客户端的共识状态。data 字段表示的二进制数据是不透明的,仅由 Wasm 合约解释。
高度
Wasm 轻客户端实例的高度由两个uint64 组成:修订号和该修订中的高度。
头部
Wasm 客户端头部的内容取决于 Wasm 合约。data 字段表示的二进制数据是不透明的,仅由 Wasm 合约解释,并且它要么是一个有效头部,要么是两个相互冲突的头部,而这两个头部都会被 Wasm 合约视为有效。在后一种情况下,合约会使用有效头部更新共识状态;在前一种情况下,轻客户端可能会检测到不当行为并冻结客户端(从而阻止后续的数据包流转)。
客户端初始化
Wasm 客户端初始化需要一个(主观选择的)最新共识状态,以及对应的、可被 Wasm 合约解释的客户端状态。合约负载消息
Wasm 客户端代理通过 Wasm VM 调用 Wasm 客户端。这些调用要求输入的负载消息分为两类判别联合类型:一类用于只执行读取的调用,另一类用于执行会改变状态的写入调用。有效性判定
Wasm 客户端的有效性检查依赖底层 Wasm 合约。如果提供的客户端消息有效,客户端状态将继续执行不当行为检查(调用checkForMisbehaviour)以及状态更新(根据是否在客户端消息中检测到不当行为,调用 updateStateOnMisbehaviour 或 updateState)。
不当行为判定
函数checkForMisbehaviour 会检查某次更新是否包含不当行为的证据。Wasm 客户端的不当行为检查用于判断同一高度上的两个冲突头部是否都足以说服该轻客户端。
状态更新
函数updateState 会对 Wasm 客户端执行一次常规更新。它会向客户端存储中添加一个共识状态。如果该头部高于 clientState 上的最新高度,那么 clientState 也会被更新。
不当行为时的状态更新
函数updateStateOnMisbehaviour 会将冻结高度设置为一个非零高度,以冻结整个客户端。
升级
此轻客户端所跟踪的链可以选择在状态中写入一个预先确定的特殊键,以允许轻客户端更新其客户端状态(例如使用新的链 ID 或修订号),为升级做准备。 由于客户端状态变更会立即执行,一旦新的客户端状态信息被写入该预先确定的键,客户端将无法再跟踪旧链上的区块,因此必须及时完成升级。提案
如果一个 Wasm 轻客户端被冻结,可以提交治理提案,用一个活动轻客户端(替代者)的状态来更新该冻结轻客户端(主体)的状态。替代客户端必须与主体客户端属于相同类型。根据底层轻客户端具体类型的不同,主体与替代客户端状态中的全部或部分参数必须一致。状态验证函数
Wasm 客户端状态验证函数会基于先前已验证的承诺根来检查证明。Wasm 合约接口
Go 与 Wasm 之间的交互
当某条指令需要在 Wasm 代码中执行时,函数会通过wasmvm 执行。
该虚拟机是沙箱化的,因此与其他操作相互隔离。
该过程需要打包要由特定函数执行的所有参数(必要时包括指向 KVStore 的指针),指定一个校验和,并提供一个 sdk.GasMeter,以便在函数执行期间正确统计 gas 使用量。
合约实例化
合约的实例化过程非常简化。传递给合约调用消息中的数据为空,但会传入 Wasm 客户端存储。这使得 Wasm 合约能够初始化其所需的任意元数据,例如已处理高度和/或已处理时间。合约查询
每个 Wasm 合约都必须支持以下查询消息:合约 sudo
每个 Wasm 合约都必须支持以下 sudo 消息:属性与不变量
由 Wasm 合约实现的底层算法所提供的正确性保证。向后兼容性
不适用。向前兼容性
只要 Wasm 合约保持其接口与ICS 02 一致,就应当具备向前兼容性。
示例实现
ICS 08 的 Go 实现可见于 ibc-go PR。历史
2021 年 10 月 8 日 - 第一版最终草案 2022 年 3 月 15 日 - 针对 02-client 重构更新 2023 年 9 月 7 日 - 针对实现过程中的变更更新 2024 年 3 月 22 日 - 针对 ibc-go 的 08-wasm 模块发布后的变更更新版权
此处所有内容均依据 Apache 2.0 许可。Synopsis
This specification document describes an interface to a light client stored as a Wasm bytecode for a blockchain.Motivation
Currently, adding a new client implementation or upgrading an existing one requires a hard upgrade because the client implementations are part of the static chain binary. Any change to the on-chain light client code depends on chain governance approving an upgrade before it can be deployed. This may be acceptable when adding new client types since the number of unique consensus algorithms that need to be supported is currently small. However, this process will become very tedious when it comes to upgrading light clients. Without dynamically upgradable light clients, a chain that wishes to upgrade its consensus algorithm (and thus break existing light clients) must wait for all counterparty chains to perform a hard upgrade that adds support for the upgraded light client before it can perform an upgrade on its chain. Examples of a consensus-breaking upgrade would be an upgrade from Tendermint v1 to a light-client breaking Tendermint v2 or switching from Tendermint consensus to Honeybadger. Changes to the internal state-machine logic will not affect consensus. E.g., changes to the staking module do not require an IBC upgrade. Requiring all counterparties to add statically new client implementations to their binaries will inevitably slow the pace of upgrades in the IBC network since the deployment of an upgrade on even a very experimental, fast-moving chain will be blocked by an upgrade to a high-value chain that will be inherently more conservative. Once the IBC network broadly adopts dynamically upgradable clients, a chain may upgrade its consensus algorithm whenever it wishes, and relayers may upgrade the client code of all counterparty chains without requiring the counterparty chains to perform an upgrade themselves. This prevents a dependency on counterparty chains when considering upgrading one’s consensus algorithm. Another reason why this interface is beneficial is that it removes the dependency between Light clients and the Go programming language. Using Wasm as a compilation target, light clients can be written in any programming language whose toolchain includes Wasm as a compilation target. Examples of these are Go, Rust, C, and C++.Definitions
Functions & terms are as defined in ICS 2.currentTimestamp is as defined in ICS 24.
Wasm VM refers to a virtual machine capable of executing valid Wasm bytecode.
Wasm Contract refers to Wasm bytecode stored in the Wasm VM, which provides a target blockchain specific implementation of ICS 2.
Wasm Client Proxy refers to an implementation of ICS 8 that acts as a pass-through to the Wasm client.
Wasm Client refers to a particular instance of Wasm Contract defined as a tuple (Wasm Contract, ClientID).
Desired properties
This specification must satisfy the client interface defined in ICS 2..Technical specification
This specification depends on the correct instantiation of the Wasm client and is decoupled from any specific implementation of the targetblockchain consensus algorithm.
Storage management
Light client operations defined in ICS 2 can be stateful; they may modify the state kept in storage. For that, there is a need to allow the underlying Wasm light client implementation to access client and consensus data structures and, after performing certain computations, to update the storage with the new versions of them. For this reason, the implementation in ibc-go chooses to share the Wasm client store between the02-client module (for reading), 08-wasm module (for instantiation), and Wasm contract. Other than instantiation, the Wasm contract is responsible for updating state.
Wasm VM
The purpose of this module is to delegate light client logic to a module written in Wasm. For that, the Wasm client proxy needs a reference (or a handler) to a Wasm VM. The Wasm client proxy can then directly call thewasmvm to interact with the VM with less overhead, fewer dependencies, and finer grain control over the Wasm client store than if using an intermediary module such as x/wasm.
Gas costs
wasmd has thoroughly benchmarked gas adjustments for CosmWasm and the same values are being applied in the Wasm VM used in ibc-go’s implementation of ICS 8.
Client state
The Wasm client state tracks the location of the Wasm bytecode viachecksum. Binary data represented by the data field is opaque and only interpreted by the Wasm contract.
Consensus state
The Wasm consensus state tracks the consensus state of the Wasm client. Binary data represented by thedata field is opaque and only interpreted by the Wasm contract.
Height
The height of a Wasm light client instance consists of twouint64s: the revision number and the height in the revision.
Headers
Contents of Wasm client headers depend upon Wasm contract. Binary data represented by thedata field is opaque and only interpreted by the Wasm contract, and will consist either of a valid header or of two conflicting headers, both of which the Wasm contract would have considered valid. In the latter case, the contract will update the consensus state with the valid header; in the former case, the light client may detect misbehaviour and freeze the client (thus preventing further packet flow).
Client initialization
Wasm client initialization requires a (subjectively chosen) latest consensus state and corresponding client state, interpretable by the Wasm contract.Contract payload messages
The Wasm client proxy performs calls to the Wasm client via the Wasm VM. The calls require as input payload messages that are categorized on two discriminated union types: one for payload messages used in calls that perform only reads, and one for payload messages used in calls that perform state-changing writes.Validity predicate
Wasm client validity checking uses underlying Wasm contract. If the provided client message is valid, the client state will proceed to checking for misbehaviour (call tocheckForMisbehaviour) and updating state (call to either updateStateOnMisbehaviour or updateState depending on whether misbehaviour was detected in the client message).
Misbehaviour predicate
FunctioncheckForMisbehaviour will check if an update contains evidence of misbehaviour. Wasm client misbehaviour checking determines whether or not two conflicting headers at the same height would have convinced the light client.
State update
FunctionupdateState will perform a regular update for the Wasm client. It will add a consensus state to the client store. If the header is higher than the latest height on the clientState, then the clientState will be updated.
State update on misbehaviour
FunctionupdateStateOnMisbehaviour will set the frozen height to a non-zero height to freeze the entire client.
Upgrades
The chain which this light client is tracking can elect to write a special pre-determined key in state to allow the light client to update its client state (e.g. with a new chain ID or revision) in preparation for an upgrade. As the client state change will be performed immediately, once the new client state information is written to the pre-determined key, the client will no longer be able to follow blocks on the old chain, so it must upgrade promptly.Proposals
If a Wasm light client becomes frozen, a governance proposal can be submitted to update the state of the frozen light client (the subject) with the state of an active light client (the substitute). The substitute client MUST be of the same type as the subject client. Depending on the exact type of the underlying light client type, all or a subset of parameters of the subject and substitute client states MUST match.State verification functions
Wasm client state verification functions check a proof against a previously validated commitment root.Wasm Contract Interface
Interaction between Go and Wasm
When an instruction needs to be executed in Wasm code, functions are executed using awasmvm.
This VM is sandboxed, hence isolated from other operations.
The process requires packaging all the arguments to be executed by a specific function (including
pointers to KVStores if needed), pointing to a checksum, and a sdk.GasMeter to properly account
for gas usage during the execution of the function.
Contract instantiation
Instantiation of a contract is minimal. No data is passed in the message for the contract call, but the Wasm client store is passed. This allows for a Wasm contract to initialize any metadata that they need such as processed height and/or processed time.Contract query
Every Wasm contract must support these query messages:Contract sudo
Every Wasm contract must support these sudo messages:Properties & Invariants
Correctness guarantees as provided by the underlying algorithm implemented by Wasm contract.Backwards Compatibility
Not applicable.Forwards Compatibility
As long as Wasm contract keeps its interface consistent withICS 02 it should be forward compatible