The IBC team at Informal Systems comprises two sub-teams who work closely together: the Hermes team and the ibc-rs team. The Hermes team primarily supports relayer operators and those who work “off-chain”. The ibc-rs team, in contrast, primarily supports maintainers of “on-chain” applications who work to integrate IBC into their codebases, enabling those applications to communicate, transfer assets, and interface with other IBC-enabled chains.
While we’ve published a few posts on the goings-on of the Hermes relayer, the ibc-rs project has received much less time in the spotlight. However, with the release of ibc-rs v1 on the horizon (targeting the first half of 2024), it’s about time we remedy that.
In essence, ibc-rs provides on-chain interfaces (all implemented in Rust) for chains to speak and grok the IBC protocol. The ibc-rs project is also sometimes colloquially referred to as the “modules”, which evokes modular pieces of logic that can be plugged into a blockchain to enable certain kinds of functionality. The ICS-20 fungible token transfermodule is perhaps the most commonly-used example. Chains looking to utilize the IBC protocol’s token transfer capabilities to send tokens to and from other IBC-enabled chains can integrate ibc-rs’s ICS-20 module in order to achieve this.
In addition to self-contained pieces of modular business logic like ICS-20, ibc-rs exports many of the core abstractions and primitives that make up the IBC protocol’s core implementation, such as client, connection, and channel abstractions. ibc-rs also makes available all of the foundational domain types and data structures upon which the higher-level abstractions are built. For use-cases that require extensive modifications to IBC, ibc-rs makes available the foundational IBC primitives, abstractions, and data structures to enable those use-cases. On the flip side, ibc-rs also exports ready-made IBC applications that chain developers can simply import and use out-of-the-box if they wish. In this way, ibc-rs allows chain developers to build upon any layer of the IBC stack.
In actuality, there were some wrinkles in ibc-rs’s ability to provide this flexibility in a frictionless and intuitive manner. Chief among these is the fact that the different abstraction layers in ibc-rs were often tangled together through many inter-dependencies, which meant that often a distinct layer of abstraction could not be imported on its own by a chain developer looking to use that layer. This meant that additional dependencies, which were often not relevant to the user, had to be pulled in in order to utilize a certain abstraction layer.
In light of this, ADR 008 was drafted in order to outline a plan for restructuring the ibc-rs repository. The overarching aim of the restructure is improve the overall usability of ibc-rs by reducing inter-dependence amongst various components and layers within the codebase. This in turn will mitigate potential dependency-related conflicts that might arise in the context of monolithic libraries.
This restructuring initiative also opens up additional use-cases that were previously unrealistic due to ibc-rs’s more tightly-coupled structure:
Selective module import: Users can now import only the necessary components and/or modules that they need for their particular use-case(s). Previously, it was impractical if a user only wanted to import the ics07-tendermint
module; doing so required importing other modules that the ics07 module itself depended upon.
Selective types import: Users can now opt to only import the types from a particular module, without having to also pull in the validation and execution logic. Previously, off-chain consumers of ibc-rs, such as relayers, were unable to only import the domain types that they needed: they would need to also pull in the modules logic that ibc-rs exports, despite the fact that none of this logic was relevant to them. In the case of the Hermes relayer, specifically, this contributed partly to the Hermes team maintaining their own IBC types. With ibc-rs’s new structure, Hermes will be able to depend instead on the types that ibc-rs exports, thus reducing code duplication across the ecosystem.
Easier development of CosmWasm contracts: Informal Systems has been working on developing a CosmWasm-based Tendermint light client. This is also happening in the context of the Sovereign IBC integration work. It is another example of a use-case that ibc-rs was not great at catering for, as it necessitated importing the entire ibc-rs codebase and its dependencies. With ibc-rs’s new structure, the light client can now be implemented by pulling in only the relevant dependencies, namely the ics07-tendermint
and the ibc-core-client
crates. Additionally, ibc-rs also now supports no-std
and no-float
compilation targets, a prerequisite for users working on CosmWasm smart contracts.
The top level of the restructured ibc-rs crate looks like this:
1// Every validator set on any consumer chain MUST either be or have been 2// a validator set on the provider chain. 3val ValidatorSetHasExistedInv = 4 runningConsumers.forall(chain => 5 getVotingPowerHistory(currentState, chain).toSet().forall( 6 validatorSet => 7 providerVotingPowerHistory.toSet().contains(validatorSet) 8 ) 9 )
With this new structure, the top-level ibc
module simply re-exports all of the other top-level modules. This serves to minimize downstream breaking changes on the end user, by allowing them to continue to use ibc-rs’s sub-crates while requiring minimal use
statement changes.
Each of the sub-crates contained in the ibc-core
, ibc-clients
, and ibc-apps
export a separate types
sub-crate, which only contains the types that that particular crate makes use of. This makes it straightforward for a downstream user of ibc-rs to know which sub-crate(s) they need to import in order to pull in the domain types that they need. Additionally, downstream users will no longer need to depend on ibc-proto
since ibc-rs
now re-exports all of the necessary proto dependencies from the relevant crates. More specifically, pulling in any ibc-rs crate will automatically pull all of the necessary proto types that are needed such that it is no longer necessary to depend on ibc-proto
, at least not solely for the sake of ibc-rs.
The ibc-core
crate exports the implementations of the core IBC layers. ibc-clients
exports the different light client implementations (of which currently only Tendermint exists in the mainline repository, though a CosmWasm light client is in the works), and ibc-apps
exports the implementation of IBC apps (of which currently only the ICS-20 token transfer app exists). The ibc-primitives
crate exports commonly-used fundamental types, such as those that belong to the proto
and alloc
crates. ibc-testkit
exports the types and utilities needed to enable rigorous integration tests for ibc-rs, while also aiding host chains to address a broad spectrum of testing scenarios during ibc-rs integration. The ibc-derive
crate provides a set of procedural macros for deriving IBC-related traits, which serve to reduce the amount of boilerplate code required to implement them. The ibc-query
crate provides utility traits, query methods, and gRPC query services for each of the IBC core client, connection, and channel layers. Lastly, the ibc-data-types
crate serves a similar purpose as the top-level ibc
crate: it re-exports the data structures from all the various types
crates that each layer exports.
Now that this proposed restructuring effort has successfully gone through, ibc-rs is in a much better spot in terms of usability; this was an important and necessary effort in getting ready for ibc-rs’s upcoming v1 launch!
If you’re interested in following along with ibc-rs’s development, follow the project’s repository and consider joining the bi-weekly IBC Core coordination calls, where we update the community on the goings-on of the project. If you’re interested in integrating IBC into your application, please reach out! We’re looking to continue generalizing ibc-rs by working with teams to fit individual use-cases and ensure that ibc-rs is able to provide the smoothest IBC adoption experience possible.