Skip to content

Commit e1f19af

Browse files
docs: ADR-010 enabling standalone ICS-02 integration (informalsystems#1116)
* docs: ADR-010 enabling standalone ICS-02 integration * imp: explaining why decode_client_state will be removed * imp: use diff-formatted code snippets * chore: put a comment for decode_client_state * chore: apply suggestions from code review Co-authored-by: Sean Chen <[email protected]> Signed-off-by: Farhad Shabani <[email protected]> * chore: apply suggestions from code review Co-authored-by: Sean Chen <[email protected]> Signed-off-by: Farhad Shabani <[email protected]> * imp: update with details for host_consensus_state & validate_self_client * nit: lint markdown * nit: rename to HostClient/ConsensusState * imp: update ADR with changes in implementation PR * chore: back to the original implementation idea * fix: adjust ClientStateDecoder * nit * nit: add comment for minimizing associated types --------- Signed-off-by: Farhad Shabani <[email protected]> Co-authored-by: Sean Chen <[email protected]>
1 parent 4f0ab6a commit e1f19af

File tree

2 files changed

+380
-0
lines changed

2 files changed

+380
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,380 @@
1+
# ADR 010: ENABLE STANDALONE ICS-02 INTEGRATION
2+
3+
## Changelog
4+
5+
- 2024-03-05: Draft Proposed
6+
7+
## Status
8+
9+
Proposed
10+
11+
## Context
12+
13+
In ADR-07, we previously granted light client developers the flexibility to
14+
introduce custom APIs to the client contexts. This decision was made to
15+
accommodate potential scenarios where not all methods required by every future
16+
light client might be present in the extensive
17+
[`ValidationContext`](https://github.com/cosmos/ibc-rs/blob/4421b0dcd6eab6c914b8c5a7d45817b1edb6b2ce/ibc-core/ics24-host/src/context.rs#L31)
18+
or
19+
[`ExecutionContext`](https://github.com/cosmos/ibc-rs/blob/4421b0dcd6eab6c914b8c5a7d45817b1edb6b2ce/ibc-core/ics24-host/src/context.rs#L168)
20+
traits.
21+
22+
In this ADR, while retaining that capability, we propose a reorganization of
23+
client-related APIs by consolidating them under the ICS-02 client validation and
24+
execution contexts. While the main top-level context traits in ICS-24
25+
(`ibc-core-host` crate) will still have access to these APIs through the
26+
existing accessor
27+
[`get_client_validation_context()`](https://github.com/cosmos/ibc-rs/blob/4421b0dcd6eab6c914b8c5a7d45817b1edb6b2ce/ibc-core/ics24-host/src/context.rs#L38)
28+
and
29+
[`get_client_execution_context()`](https://github.com/cosmos/ibc-rs/blob/4421b0dcd6eab6c914b8c5a7d45817b1edb6b2ce/ibc-core/ics24-host/src/context.rs#L170)
30+
methods.
31+
32+
As a result of this ADR, client relevant methods, namely **`client_state()`**
33+
and **`consensus_state()`**, will be extracted from the large ICS-24 validation
34+
and execution context traits. Instead, they will find their new home under the
35+
ICS-02
36+
[`ClientValidationContext`](https://github.com/cosmos/ibc-rs/blob/caee889ad308a4aac3f9905de9cdda76c5533cfb/ibc-core/ics02-client/context/src/context.rs#L14)
37+
and
38+
[`ClientExecutionContext`](https://github.com/cosmos/ibc-rs/blob/caee889ad308a4aac3f9905de9cdda76c5533cfb/ibc-core/ics02-client/context/src/context.rs#L32)
39+
traits.
40+
41+
## Objectives
42+
43+
The primary objective is to enhance the delineation of the APIs that connect
44+
ibc-rs to the host’s storage, offering a more modular approach that allows
45+
developers who wish to integrate only the implemented client states under the
46+
ibc-rs to their IBC infra. In other words, this enhancement does not mandate
47+
hosts to implement all the IBC layers, such as connection, channel, or any of
48+
the IBC applications, when only light client support is required.
49+
50+
As a result, this ADR sets the stage for several potential use cases, including:
51+
52+
1. **Streamlines CosmWasm light client implementation**
53+
- Since the refined structure allows for the independent integration of
54+
ICS-02 client traits into the storage, it becomes straightforward to
55+
implement light clients living in ibc-rs as CosmWasm contracts, which
56+
empowers simpler Wasm client integration with ibc-go driven chains.
57+
58+
2. **Enables client integration with various IBC implementations**
59+
- Any IBC implementation, whether it is based on ibc-rs or a fork of ibc-rs,
60+
will have this capability to incorporate the latest light client
61+
implementations by ibc-rs. So that even if an IBC implementation diverges
62+
from the ibc-rs framework, hosts can benefit from the latest version of
63+
light client implementation. This is important from the security
64+
standpoint, broadens the applicability of ibc-rs, and facilitates
65+
collaboration with other IBC-adjacent solutions.
66+
67+
As part of this ADR and to minimize breaking changes later, we aim to address
68+
the following client-relevant API deficiencies as well:
69+
70+
1. **Refining access to validation vs execution methods**
71+
- So far, unauthorized access to client execution methods [has been
72+
possible](https://github.com/cosmos/ibc-rs/blob/4421b0dcd6eab6c914b8c5a7d45817b1edb6b2ce/ibc-core/ics24-host/src/context.rs#L33)
73+
under the `ValidationContext`. This will be rectified to ensure that only
74+
the `ClientState` validation method is callable within the validation
75+
contexts. This enhances the precision of access control, aligning it more
76+
closely with the intended functionality.
77+
78+
2. **Bringing more clarity to how context APIs are related**
79+
- The ambiguous relationship between the main context APIs at ICS-24, ICS-02
80+
client APIs, and client-specific APIs can get cleared. This ADR aims for a
81+
more transparent relationship between these contexts, making it easier to
82+
understand their interactions and roles. For instance some client relevant
83+
methods are located under the client contexts, while others are under the
84+
main (ICS-24) contexts.
85+
86+
3. **Minimizing associated types’ declarations**
87+
- Our current APIs pose a challenge by requiring users to introduce multiple
88+
yet the same associated types like `AnyClientState`, `AnyConsensusState`,
89+
etc across different layers. A more efficient solution involves
90+
introducing such types in fewer places, providing better access to the
91+
traits across different layers. However, it's worth acknowledging that an
92+
ideal solution might entail utilizing features from forthcoming stable
93+
versions of Rust. This would enable us to leverage the advantages provided
94+
by either
95+
[associated_type_bounds](https://rust-lang.github.io/rfcs/2289-associated-type-bounds.html),
96+
[associated_type_defaults](https://rust-lang.github.io/rfcs/2532-associated-type-defaults.html),
97+
or
98+
[implied_bounds](https://rust-lang.github.io/rfcs/2089-implied-bounds.html)
99+
capabilities.
100+
101+
## Decision
102+
103+
Here is a high-level diagram that illustrates the optimal boundaries for each
104+
context trait, specifying the scope of access by each of these contexts. In
105+
addition, the classification of APIs should be such that they allow the
106+
independent integration of light client implementations.
107+
108+
<div style="text-align: center;">
109+
<img src="./assets/adr010.png" alt="Main components" width="800" height="600">
110+
</div>
111+
112+
The primary `ValidationContext` and `ExecutionContext` traits at the ICS-24 host
113+
level will be restructured as follows, only having sufficient access to
114+
respective ICS-02 client contexts, without caring about the types or methods
115+
associated with client or consensus states of counterparty chains. It is
116+
noteworthy that, to better illustrate the desired outcome from the current
117+
state, the code snippets below are in the `diff` format.
118+
119+
```diff
120+
pub trait ValidationContext {
121+
type V: ClientValidationContext;
122+
+ type HostClientState: ClientStateValidation<Self::V>;
123+
+ type HostConsensusState: ConsensusState;
124+
- type E: ClientExecutionContext;
125+
- type AnyConsensusState: ConsensusState;
126+
- type AnyClientState: ClientState<Self::V, Self::E>;
127+
128+
/// Retrieve the context that implements all clients' `ValidationContext`.
129+
fn get_client_validation_context(&self) -> &Self::V;
130+
131+
// This method will be removed and replaced by a `ClientStateDecoder` trait that will encapsulate the ability to decode a client state from an `Any`
132+
- fn decode_client_state(&self, client_state: Any) -> Result<Self::AnyClientState, ContextError>;
133+
134+
- fn client_state(&self, client_id: &ClientId) -> Result<Self::AnyClientState, ContextError>;
135+
136+
- fn consensus_state(
137+
- &self,
138+
- client_cons_state_path: &ClientConsensusStatePath,
139+
- ) -> Result<Self::AnyConsensusState, ContextError>;
140+
141+
fn host_consensus_state(
142+
&self,
143+
height: &Height,
144+
- ) -> Result<Self::AnyConsensusState, ContextError>;
145+
+ ) -> Result<Self::HostConsensusState, ContextError>;
146+
147+
fn validate_self_client(
148+
&self,
149+
- client_state_of_host_on_counterparty: Any,
150+
+ client_state_of_host_on_counterparty: Self::HostClientState,
151+
) -> Result<(), ContextError>;
152+
153+
... // other methods
154+
}
155+
156+
pub trait ExecutionContext: ValidationContext {
157+
+ type E: ClientExecutionContext;
158+
159+
/// Retrieve the context that implements all clients' `ExecutionContext`.
160+
fn get_client_execution_context(&mut self) -> &mut Self::E;
161+
162+
... // other methods
163+
164+
/// Convenient type aliases
165+
+ pub type ClientStateRef<Ctx> =
166+
+ <<Ctx as ValidationContext>::V as ClientValidationContext>::ClientStateRef;
167+
168+
+ pub type ClientStateMut<Ctx> =
169+
+ <<Ctx as ExecutionContext>::E as ClientExecutionContext>::ClientStateMut;
170+
171+
+ pub type ConsensusStateRef<Ctx> =
172+
+ <<Ctx as ValidationContext>::V as ClientValidationContext>::ConsensusStateRef;
173+
}
174+
```
175+
176+
We should also highlight that ICS-02 houses various types, APIs and
177+
implementations essential for enabling **light clients of counterparty chains
178+
operating on the host chain**. Therefore, the `host_consensus_state()` and
179+
`validate_self_client()` methods, though initially appearing to be ICS-02
180+
specific, play a crucial role in the connection handshake validating receiving
181+
datagrams against the client and consensus states of the host.
182+
183+
In this ADR, these methods will continue to be housed under the main context
184+
traits. However, we will explicitly define the accepted types for these methods
185+
as `HostClientState` and `HostConsensusState`. This refinement aims for more
186+
clarity and will optimize the decoding process, removing an unnecessary layer of
187+
decoding during information retrieval. Previously, the decoding process for
188+
these methods involved obtaining `AnyClientState` and `AnyConsensusState` types
189+
and then converting them into the concrete `HostClientState` and
190+
`HostConsensusState` types.
191+
192+
Following the aforementioned points, in the ICS-02 level, the
193+
`ClientValidationContext` and `ClientExecutionContext` traits will be
194+
restructured as follows, containing all the client relevant methods and types:
195+
196+
```diff
197+
pub trait ClientValidationContext: Sized {
198+
// Given that we will be dropping `decode_client_state()` method,
199+
// the client state type introduced here should have implemented `TryFrom<Any>` and `Into<Any>` traits.
200+
+ type ClientStateRef: ClientStateValidation<Self>;
201+
+ type ConsensusStateRef: ConsensusState;
202+
203+
+ fn client_state(&self, client_id: &ClientId) -> Result<Self::ClientStateRef, ContextError>;
204+
205+
+ fn consensus_state(
206+
+ &self,
207+
+ client_cons_state_path: &ClientConsensusStatePath,
208+
+ ) -> Result<Self::ConsensusStateRef, ContextError>;
209+
210+
fn client_update_meta(
211+
&self,
212+
client_id: &ClientId,
213+
height: &Height,
214+
) -> Result<(Timestamp, Height), ContextError>;
215+
}
216+
217+
pub trait ClientExecutionContext:
218+
+ ClientValidationContext<ClientStateRef = Self::ClientStateMut>
219+
{
220+
- type V: ClientValidationContext;
221+
- type AnyClientState: ClientState<Self::V, Self>;
222+
- type AnyConsensusState: ConsensusState;
223+
+ type ClientStateMut: ClientStateExecution<Self>;
224+
225+
+ fn client_state_mut(&self, client_id: &ClientId) -> Result<Self::ClientStateMut, ContextError> {
226+
+ self.client_state(client_id)
227+
+ }
228+
229+
fn store_client_state(
230+
&mut self,
231+
client_state_path: ClientStatePath,
232+
client_state: Self::ClientStateMut,
233+
) -> Result<(), ContextError>;
234+
235+
fn store_consensus_state(
236+
&mut self,
237+
consensus_state_path: ClientConsensusStatePath,
238+
consensus_state: Self::ConsensusStateRef,
239+
) -> Result<(), ContextError>;
240+
241+
fn delete_consensus_state(
242+
&mut self,
243+
consensus_state_path: ClientConsensusStatePath,
244+
) -> Result<(), ContextError>;
245+
246+
fn store_update_meta(
247+
&mut self,
248+
client_id: ClientId,
249+
height: Height,
250+
host_timestamp: Timestamp,
251+
host_height: Height,
252+
) -> Result<(), ContextError>;
253+
254+
fn delete_update_meta(
255+
&mut self,
256+
client_id: ClientId,
257+
height: Height,
258+
) -> Result<(), ContextError>;
259+
}
260+
```
261+
262+
The introduction of the `ClientStateMut` associated type in addition to the
263+
`ClientStateRef` became necessary to tackle the limitation that the
264+
`ClientState` retrieved from the regular `client_state()` method provides access
265+
only to validation methods. However, in `execute` handlers, there are scenarios
266+
(like
267+
[here](https://github.com/cosmos/ibc-rs/blob/f272f30e0f773d85a99fc553b75d41f9f768d5c5/ibc-core/ics02-client/src/handler/update_client.rs#L54))
268+
where access to the execution methods of the client state is required. We aim to
269+
simplify the user experience by providing a default implementation, relieving
270+
users from the need to implement the `client_state_mut` method.
271+
272+
Also, the introduction of `<ClientStateRef = Self::ClientStateMut>` is prompted
273+
by the need to address the characteristics of concrete `ClientState`
274+
definitions. For instance, in the case of ICS-07, such as `TmClientState`, the
275+
struct definition can't be split into two fragments, one for validation and the
276+
other for execution. Therefore, contexts implementing `ClientExecutionContext`
277+
must introduce a `ClientStateMut` type the same as `ClientStateRef`.
278+
279+
With the mentioned classification, we can now streamline ICS-07 specific APIs,
280+
eliminating the requirement for implementing a redundant `consensus_state()`
281+
method. For the sake of simplification, we can remove the `CommonContext` trait
282+
and consolidate everything under the `TmValidationContext` as follows:
283+
284+
```diff
285+
+ /// Enables conversion (`TryInto` and `From`) between the consensus state type
286+
+ /// used by the host and the one specific to the Tendermint light client, which
287+
+ /// is `ConsensusStateType`.
288+
+ pub trait ConsensusStateConverter:
289+
+ TryInto<ConsensusStateType, Error = ClientError> + From<ConsensusStateType>
290+
+ {
291+
+ }
292+
293+
+ impl<C> ConsensusStateConverter for C where
294+
+ C: TryInto<ConsensusStateType, Error = ClientError> + From<ConsensusStateType>
295+
+ {
296+
+ }
297+
298+
- pub trait CommonContext {
299+
- // methods will be moved to the below `ValidationContext`
300+
- }
301+
302+
// Client's context required during validation
303+
pub trait ValidationContext:
304+
+ ClientValidationContext<ConsensusStateRef = Self::AnyConsensusState>
305+
{
306+
+ type ConversionError: ToString;
307+
+ type AnyConsensusState: TryInto<TmConsensusState, Error = Self::ConversionError>;
308+
309+
+ fn host_timestamp(&self) -> Result<Timestamp, ContextError>;
310+
311+
+ fn host_height(&self) -> Result<Height, ContextError>;
312+
313+
- fn consensus_state(
314+
- &self,
315+
- client_cons_state_path: &ClientConsensusStatePath,
316+
- ) -> Result<Self::AnyConsensusState, ContextError>;
317+
318+
+ fn consensus_state_heights(&self, client_id: &ClientId) -> Result<Vec<Height>, ContextError>;
319+
320+
fn next_consensus_state(
321+
&self,
322+
client_id: &ClientId,
323+
height: &Height,
324+
) -> Result<Option<Self::AnyConsensusState>, ContextError>;
325+
326+
fn prev_consensus_state(
327+
&self,
328+
client_id: &ClientId,
329+
height: &Height,
330+
) -> Result<Option<Self::AnyConsensusState>, ContextError>;
331+
}
332+
333+
-impl<T> ExecutionContext for T where T: CommonContext + ClientExecutionContext {}
334+
+impl<T> ExecutionContext for T where T: ValidationContext + ClientExecutionContext {}
335+
336+
```
337+
338+
### Remarks
339+
340+
- We move away from the `decode_client_state()` method. Since per our design,
341+
users must utilize a `ClientState` type that implements both `TryFrom<Any>`
342+
and `Into<Any>`, therefore, we can offer a trait called `ClientStateDecoder`
343+
as follows, making it readily available for users seeking to decode/encode a
344+
client state from/into the `Any` type:
345+
346+
```rust
347+
pub trait ClientStateDecoder: TryFrom<Any, Error = ClientError> + Into<Any> {}
348+
349+
impl<T> ClientStateDecoder for T where T: TryFrom<Any, Error = ClientError> {}
350+
351+
```
352+
353+
- We will maintain the `client_counter()` and `increase_client_counter()`
354+
methods within the main context traits. This stems from the fact that light
355+
clients do not rely on the relative positions in their processes.
356+
Additionally, these counters are globally tracked, and only IBC handlers
357+
invoke these methods for setting or retrieving client identifiers.
358+
359+
## Consequences
360+
361+
### Positive
362+
363+
- Enables easy light client integration without the need for integrating the
364+
entire IBC stack
365+
- Establishes a clearer relationship between APIs (ICS-02 <> ICS-24), promoting
366+
better development practices
367+
- Eliminates redundant methods/types, enhancing integration efficiency
368+
- Methods under the client contexts will align more with ibc-go client keepers,
369+
improving interoperability.
370+
371+
### Negative
372+
373+
- Some challenges may arise in identifying trait bounds during a light client
374+
implementation.
375+
- Introducing user-importable type aliases helps mitigate this concern.
376+
- Additionally, this ADR employs significant breaking changes to the hosts.
377+
378+
## References
379+
380+
- [Issue link](https://github.com/cosmos/ibc-rs/issues/1114)

docs/architecture/assets/adr010.png

168 KB
Loading

0 commit comments

Comments
 (0)