ibc-go v7.5.0 and v8.3.0 introduce two new features: Interchain Accounts (ICA) queries and conditional clients, respectively.
ICA queries benefit users who want to send queries within an ICA transaction. Conditional clients are an important component for interoperability between rollups and Cosmos SDK chains via IBC.
This post explains these new features, why they are important, and how projects can leverage them.
The initial design of Interchain Accounts (ICA) only allowed transactions to be sent and executed on a counterparty chain. It did not support a query API, which was one of the painpoints faced by ICA users.
Certain cross-chain use cases require knowledge of a particular state variable on a counterparty prior to executing a transaction. For instance, an application on Injective might want to use Osmosis to swap 100 INJ to USDC. Once the tokens have been sent and swapped, due to potential slippage, the exact amount of USDC received cannot be predetermined and must be queried before executing subsequent actions.
To address this, ibc-go v7.5.0 introduces a new ICA message MsgModuleQuerySafe
that host chains can use to query modules - only those Cosmos SDK modules marked as module_query_safe - and return the query result in the acknowledgement. Cosmos SDK v0.47 introduced a new cosmos.query.v1.modulequerysafe
protobuf annotation used to state that a query is safe to be called from within the state machine.
Best practice: We highly recommend Cosmos SDK module developers to mark their modules with the module_query_safe
tag where applicable. This tag informs ICA users which queries are module safe, enhancing the utility of this
Existing users of ICA controller can upgrade to v7.5.0 to use this new feature. If they wish to use the feature while remaining on a previous version, then the transaction bytes for MsgModuleQuerySafe
can be generated using any of the following methods:
Using CosmWasm
Using the host chain’s CLI
Using frontend logic
Using a Go client
Users of ICA host must upgrade to v7.5.0 to allow modules on their chain to be queried. If you would like more details on using this feature, please refer to our documentation.
Conditional clients are light clients that are dependent on another client to verify or update their state.
They are essential for integration with modular blockchains that break up a logical blockchain into several constituent parts.
In its initial design, ibc-go did not support direct queries between light client modules. Interaction was limited to the 02-client
module, which could invoke various light client types, but these clients could not interact among themselves.
This limitation was particularly challenging for integration with rollups, which delegate core blockchain functionality (like execution, settlement, consensus, and data availability) to separate components. A single light client can no longer independently verify a transaction because its validity is contingent upon the actions of a sequencer/sequencer set and the availability of data.
With the release of conditional clients in ibc-go v8.3.0, light clients - both native Go clients and Wasm clients - can query one another through gRPC to execute code conditional upon the state of other light client modules/contracts. To achieve this inter-client dependency, we’ve added a new VerifyMembership
gRPC query handler to the 02-client
module.
Consider a transaction from a Rollkit optimistic rollup to a Cosmos chain like Osmosis. Here’s how a Tendermint light client and a conditional client using 08-wasm
might interact:
An IBC packet is sent from the rollup to Osmosis.
The block containing the packet is submitted to a Data Availability (DA) layer, such as Celestia.
A relayer updates the Celestia (modified tendermint) client on Osmosis.
The relayer then updates the rollup light client i.e. the conditional client on Osmosis using 08-wasm
. Within this update client message, the relayer submits two proofs:
Proof #1: To prove inclusion of the rollup block header on Celestia.
Proof #2: To prove inclusion of the packet commitment within the block header. Proof #2 will not be accepted unless proof #1 is verified.
The rollup light client sends a QueryVerifyMembershipProofRequest
for the inclusion of the block header on Celestia's tendermint client.
If the query returns true, the conditional client performs proof verification to check the inclusion of packet commitment within the block header.
If both proofs are verified successfully, then the fraud window gets initiated.
In the case of misbehaviour, a fraud proof is submitted to the conditional client.
The conditional client then verifies the invalid state transition and returns success if the Celestia client also verifies the block header in question.
Once the invalid transaction has been proven, the conditional client can be updated as needed (perhaps marking all heights after the proved misbehaviour as invalid).
In the non-misbehaviour case, tokens are successfully received on Osmosis.
Important: Conditional clients should not be used for optimistic rollups without working fraud proofs! The team at Celestia is currently working on implementing fraud proofs, and they are expected to go live in production by Q3 this year.
The release of ibc-go v7.5.0 and v8.3.0 introduces ICA queries and conditional clients, respectively. The former allows for queries natively within ICA, which has been a highly requested feature from existing ICA users, while the latter opens up the possibility for inter-client dependencies, laying the foundation for cross-rollup interaction.
If you have any questions, comments or concerns, feel free to reach out to us on our Discord.
When adding the module_query_safe
tag to your module, ensure the following:
the query is deterministic and won't introduce state-machine-breaking changes without coordinated upgrades. it has its gas tracked, to avoid the attack vector where no gas is accounted for on potentially high-computation queries.
Refer to the Cosmos SDK docs to learn more.