ibc_client_cw/context/
custom_ctx.rs

1//! Implementation of the `ExtClientValidationContext` trait for the `Context`
2//! type.
3use core::fmt::Display;
4
5use ibc_core::client::context::prelude::*;
6use ibc_core::client::types::Height;
7use ibc_core::host::types::error::HostError;
8use ibc_core::host::types::identifiers::ClientId;
9use ibc_core::host::types::path::ClientConsensusStatePath;
10use ibc_core::primitives::proto::Any;
11use ibc_core::primitives::Timestamp;
12
13use super::Context;
14use crate::api::ClientType;
15use crate::types::HeightTravel;
16
17impl<'a, C: ClientType<'a>> ExtClientValidationContext for Context<'a, C>
18where
19    <C::ClientState as TryFrom<Any>>::Error: Display,
20    <C::ConsensusState as TryFrom<Any>>::Error: Display,
21{
22    fn host_timestamp(&self) -> Result<Timestamp, HostError> {
23        let time = self.env().block.time;
24
25        let host_timestamp = Timestamp::from_nanoseconds(time.nanos());
26
27        Ok(host_timestamp)
28    }
29
30    fn host_height(&self) -> Result<Height, HostError> {
31        let host_height =
32            Height::new(0, self.env().block.height).map_err(HostError::invalid_state)?;
33
34        Ok(host_height)
35    }
36
37    fn consensus_state_heights(&self, _client_id: &ClientId) -> Result<Vec<Height>, HostError> {
38        let heights = self.get_heights()?;
39
40        Ok(heights)
41    }
42    fn next_consensus_state(
43        &self,
44        client_id: &ClientId,
45        height: &Height,
46    ) -> Result<Option<Self::ConsensusStateRef>, HostError> {
47        let next_height = self.get_adjacent_height(height, HeightTravel::Next)?;
48
49        match next_height {
50            Some(h) => {
51                let cons_state_path = ClientConsensusStatePath::new(
52                    client_id.clone(),
53                    h.revision_number(),
54                    h.revision_height(),
55                );
56                self.consensus_state(&cons_state_path).map(Some)
57            }
58            None => Ok(None),
59        }
60    }
61
62    fn prev_consensus_state(
63        &self,
64        client_id: &ClientId,
65        height: &Height,
66    ) -> Result<Option<Self::ConsensusStateRef>, HostError> {
67        let prev_height = self.get_adjacent_height(height, HeightTravel::Prev)?;
68
69        match prev_height {
70            Some(prev_height) => {
71                let cons_state_path = ClientConsensusStatePath::new(
72                    client_id.clone(),
73                    prev_height.revision_number(),
74                    prev_height.revision_height(),
75                );
76                self.consensus_state(&cons_state_path).map(Some)
77            }
78            None => Ok(None),
79        }
80    }
81}