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