From 5e1ec845e4b140768142fa4ffb4f63c2690e85ae Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Fri, 19 Apr 2024 15:52:03 +0200 Subject: [PATCH 01/19] only consider ITERATE_CONSENSUS_STATE_PREFIX keys --- ibc-clients/cw-context/src/context/mod.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ibc-clients/cw-context/src/context/mod.rs b/ibc-clients/cw-context/src/context/mod.rs index 19b6d0006..de9032310 100644 --- a/ibc-clients/cw-context/src/context/mod.rs +++ b/ibc-clients/cw-context/src/context/mod.rs @@ -133,6 +133,7 @@ impl<'a, C: ClientType<'a>> Context<'a, C> { let iterator = self.storage_ref().range(None, None, Order::Ascending); let heights: Vec<_> = iterator + .filter(|(key, _)| key.starts_with(ITERATE_CONSENSUS_STATE_PREFIX.as_bytes())) .filter_map(|(_, value)| parse_height(value).transpose()) .collect::>()?; @@ -160,7 +161,7 @@ impl<'a, C: ClientType<'a>> Context<'a, C> { }; iterator - .next() + .find(|(key, _)| key.starts_with(ITERATE_CONSENSUS_STATE_PREFIX.as_bytes())) .map_or(Ok(None), |(_, height)| parse_height(height)) } @@ -195,7 +196,8 @@ impl<'a, C: ClientType<'a>> Context<'a, C> { let iterator = self .storage_ref() - .range(Some(&start_key), None, Order::Ascending); + .range(Some(&start_key), None, Order::Ascending) + .filter(|(key, _)| key.starts_with(ITERATE_CONSENSUS_STATE_PREFIX.as_bytes())); for (_, encoded_height) in iterator { let height = parse_height(encoded_height)?; From db933581aa44a95c33d04000f0bd42c52992f1dd Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Fri, 19 Apr 2024 15:56:46 +0200 Subject: [PATCH 02/19] use proto codec --- .../cw-context/src/context/client_ctx.rs | 3 ++- ibc-clients/cw-context/src/utils/mod.rs | 26 +++++-------------- 2 files changed, 9 insertions(+), 20 deletions(-) diff --git a/ibc-clients/cw-context/src/context/client_ctx.rs b/ibc-clients/cw-context/src/context/client_ctx.rs index ca1b2f6f9..d6f8ca308 100644 --- a/ibc-clients/cw-context/src/context/client_ctx.rs +++ b/ibc-clients/cw-context/src/context/client_ctx.rs @@ -156,7 +156,8 @@ impl<'a, C: ClientType<'a>> ClientExecutionContext for Context<'a, C> { let iteration_key = iteration_key(height.revision_number(), height.revision_height()); - let height_vec = height.to_string().into_bytes(); + // protobuf encoding + let height_vec = height.encode_vec(); self.insert(iteration_key, height_vec); diff --git a/ibc-clients/cw-context/src/utils/mod.rs b/ibc-clients/cw-context/src/utils/mod.rs index 612a46d5c..51f223805 100644 --- a/ibc-clients/cw-context/src/utils/mod.rs +++ b/ibc-clients/cw-context/src/utils/mod.rs @@ -2,24 +2,12 @@ mod codec; pub use codec::*; use ibc_core::client::types::error::ClientError; -use ibc_core::client::types::{Height, HeightError}; +use ibc_core::client::types::Height; +use ibc_core::primitives::proto::Protobuf; -/// Decodes a `Height` from a UTF-8 encoded byte array. -pub fn parse_height(encoded_height: Vec) -> Result, ClientError> { - let height_str = match alloc::str::from_utf8(encoded_height.as_slice()) { - Ok(s) => s, - // In cases where the height is unavailable, the encoded representation - // might not be valid UTF-8, resulting in an invalid string. In such - // instances, we return None. - Err(_) => return Ok(None), - }; - match Height::try_from(height_str) { - Ok(height) => Ok(Some(height)), - // This is a valid case, as the key may contain other data. We just skip - // it. - Err(HeightError::InvalidFormat { .. }) => Ok(None), - Err(e) => Err(ClientError::Other { - description: e.to_string(), - }), - } +/// Decodes a `Height` from a Protobuf encoded byte array. +pub fn parse_height(encoded_height: Vec) -> Result { + Height::decode_vec(&encoded_height).map_err(|e| ClientError::Other { + description: e.to_string(), + }) } From 8aa653b51f51827f7697e686d6cf2e8d0b093d68 Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Fri, 19 Apr 2024 16:01:25 +0200 Subject: [PATCH 03/19] refactor with updated parse_height type sig --- ibc-clients/cw-context/src/context/mod.rs | 36 ++++++++++------------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/ibc-clients/cw-context/src/context/mod.rs b/ibc-clients/cw-context/src/context/mod.rs index de9032310..fe998569c 100644 --- a/ibc-clients/cw-context/src/context/mod.rs +++ b/ibc-clients/cw-context/src/context/mod.rs @@ -132,12 +132,10 @@ impl<'a, C: ClientType<'a>> Context<'a, C> { pub fn get_heights(&self) -> Result, ClientError> { let iterator = self.storage_ref().range(None, None, Order::Ascending); - let heights: Vec<_> = iterator + iterator .filter(|(key, _)| key.starts_with(ITERATE_CONSENSUS_STATE_PREFIX.as_bytes())) - .filter_map(|(_, value)| parse_height(value).transpose()) - .collect::>()?; - - Ok(heights) + .map(|(_, value)| parse_height(value)) + .collect::>() } /// Searches for either the earliest next or latest previous height based on @@ -162,7 +160,8 @@ impl<'a, C: ClientType<'a>> Context<'a, C> { iterator .find(|(key, _)| key.starts_with(ITERATE_CONSENSUS_STATE_PREFIX.as_bytes())) - .map_or(Ok(None), |(_, height)| parse_height(height)) + .map(|(_, height)| parse_height(height)) + .transpose() } /// Returns the key for the client update time. @@ -202,21 +201,16 @@ impl<'a, C: ClientType<'a>> Context<'a, C> { for (_, encoded_height) in iterator { let height = parse_height(encoded_height)?; - match height { - Some(height) => { - let processed_height_key = self.client_update_height_key(&height); - metadata.push(GenesisMetadata { - key: processed_height_key.clone(), - value: self.retrieve(&processed_height_key)?, - }); - let processed_time_key = self.client_update_time_key(&height); - metadata.push(GenesisMetadata { - key: processed_time_key.clone(), - value: self.retrieve(&processed_time_key)?, - }); - } - None => continue, - } + let processed_height_key = self.client_update_height_key(&height); + metadata.push(GenesisMetadata { + key: processed_height_key.clone(), + value: self.retrieve(&processed_height_key)?, + }); + let processed_time_key = self.client_update_time_key(&height); + metadata.push(GenesisMetadata { + key: processed_time_key.clone(), + value: self.retrieve(&processed_time_key)?, + }); } let iterator = self From b88734b955b79bb16ef16e769c745510fb51d8a0 Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Fri, 19 Apr 2024 16:03:19 +0200 Subject: [PATCH 04/19] encode and decode height funcs --- ibc-clients/cw-context/src/context/client_ctx.rs | 5 ++--- ibc-clients/cw-context/src/context/mod.rs | 8 ++++---- ibc-clients/cw-context/src/utils/mod.rs | 7 ++++++- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/ibc-clients/cw-context/src/context/client_ctx.rs b/ibc-clients/cw-context/src/context/client_ctx.rs index d6f8ca308..63aad8ee3 100644 --- a/ibc-clients/cw-context/src/context/client_ctx.rs +++ b/ibc-clients/cw-context/src/context/client_ctx.rs @@ -13,7 +13,7 @@ use ibc_core::primitives::Timestamp; use super::Context; use crate::api::ClientType; -use crate::utils::AnyCodec; +use crate::utils::{encode_height, AnyCodec}; impl<'a, C: ClientType<'a>> ClientValidationContext for Context<'a, C> { type ClientStateRef = C::ClientState; @@ -156,8 +156,7 @@ impl<'a, C: ClientType<'a>> ClientExecutionContext for Context<'a, C> { let iteration_key = iteration_key(height.revision_number(), height.revision_height()); - // protobuf encoding - let height_vec = height.encode_vec(); + let height_vec = encode_height(height); self.insert(iteration_key, height_vec); diff --git a/ibc-clients/cw-context/src/context/mod.rs b/ibc-clients/cw-context/src/context/mod.rs index fe998569c..feeae5362 100644 --- a/ibc-clients/cw-context/src/context/mod.rs +++ b/ibc-clients/cw-context/src/context/mod.rs @@ -18,7 +18,7 @@ use prost::Message; use crate::api::ClientType; use crate::types::{ContractError, GenesisMetadata, HeightTravel, MigrationPrefix}; -use crate::utils::{parse_height, AnyCodec}; +use crate::utils::{decode_height, AnyCodec}; type Checksum = Vec; @@ -134,7 +134,7 @@ impl<'a, C: ClientType<'a>> Context<'a, C> { iterator .filter(|(key, _)| key.starts_with(ITERATE_CONSENSUS_STATE_PREFIX.as_bytes())) - .map(|(_, value)| parse_height(value)) + .map(|(_, value)| decode_height(value)) .collect::>() } @@ -160,7 +160,7 @@ impl<'a, C: ClientType<'a>> Context<'a, C> { iterator .find(|(key, _)| key.starts_with(ITERATE_CONSENSUS_STATE_PREFIX.as_bytes())) - .map(|(_, height)| parse_height(height)) + .map(|(_, height)| decode_height(height)) .transpose() } @@ -199,7 +199,7 @@ impl<'a, C: ClientType<'a>> Context<'a, C> { .filter(|(key, _)| key.starts_with(ITERATE_CONSENSUS_STATE_PREFIX.as_bytes())); for (_, encoded_height) in iterator { - let height = parse_height(encoded_height)?; + let height = decode_height(encoded_height)?; let processed_height_key = self.client_update_height_key(&height); metadata.push(GenesisMetadata { diff --git a/ibc-clients/cw-context/src/utils/mod.rs b/ibc-clients/cw-context/src/utils/mod.rs index 51f223805..25dd68e5f 100644 --- a/ibc-clients/cw-context/src/utils/mod.rs +++ b/ibc-clients/cw-context/src/utils/mod.rs @@ -5,8 +5,13 @@ use ibc_core::client::types::error::ClientError; use ibc_core::client::types::Height; use ibc_core::primitives::proto::Protobuf; +/// Encodes a `Height` into a Protobuf encoded byte array. +pub fn encode_height(height: Height) -> Vec { + height.encode_vec() +} + /// Decodes a `Height` from a Protobuf encoded byte array. -pub fn parse_height(encoded_height: Vec) -> Result { +pub fn decode_height(encoded_height: Vec) -> Result { Height::decode_vec(&encoded_height).map_err(|e| ClientError::Other { description: e.to_string(), }) From ebfbb7b8e9165bfdb2e21a03e652c431ef15b00e Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Fri, 19 Apr 2024 16:08:42 +0200 Subject: [PATCH 05/19] fix clippy --- ibc-clients/cw-context/src/lib.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/ibc-clients/cw-context/src/lib.rs b/ibc-clients/cw-context/src/lib.rs index 792811815..b1f72df01 100644 --- a/ibc-clients/cw-context/src/lib.rs +++ b/ibc-clients/cw-context/src/lib.rs @@ -18,8 +18,6 @@ )] #![forbid(unsafe_code)] -extern crate alloc; - pub mod api; pub mod context; pub mod handlers; From 4de6db954b3e681e21ff1fa472c6e61d692f7319 Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Fri, 19 Apr 2024 16:17:44 +0200 Subject: [PATCH 06/19] rm redundant type annotation --- ibc-clients/cw-context/src/context/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ibc-clients/cw-context/src/context/mod.rs b/ibc-clients/cw-context/src/context/mod.rs index feeae5362..312347852 100644 --- a/ibc-clients/cw-context/src/context/mod.rs +++ b/ibc-clients/cw-context/src/context/mod.rs @@ -135,7 +135,7 @@ impl<'a, C: ClientType<'a>> Context<'a, C> { iterator .filter(|(key, _)| key.starts_with(ITERATE_CONSENSUS_STATE_PREFIX.as_bytes())) .map(|(_, value)| decode_height(value)) - .collect::>() + .collect() } /// Searches for either the earliest next or latest previous height based on From f5bc322c104c22ade35c64b0a1b9658ab5c0bbb1 Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Fri, 19 Apr 2024 18:33:26 +0200 Subject: [PATCH 07/19] add changelog entry --- .../1175-cw-consensus-state-height-iteration-codec.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .changelog/unreleased/bug-fixes/1175-cw-consensus-state-height-iteration-codec.md diff --git a/.changelog/unreleased/bug-fixes/1175-cw-consensus-state-height-iteration-codec.md b/.changelog/unreleased/bug-fixes/1175-cw-consensus-state-height-iteration-codec.md new file mode 100644 index 000000000..30f2793da --- /dev/null +++ b/.changelog/unreleased/bug-fixes/1175-cw-consensus-state-height-iteration-codec.md @@ -0,0 +1,4 @@ +- [ibc-clients/cw-context] Fix `ConsensusState` height iteration. + ([\#1175](https://github.com/cosmos/ibc-rs/issues/1175)) +- [ibc-clients/cw-context] Encode and decode `ConsensusState` heights using + Protobuf. ([\#1176](https://github.com/cosmos/ibc-rs/issues/1176)) From 94683f4601ed610f7a6faba797f077e49e42720b Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Fri, 19 Apr 2024 18:34:31 +0200 Subject: [PATCH 08/19] correct link on changelog --- .../bug-fixes/1175-cw-consensus-state-height-iteration-codec.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changelog/unreleased/bug-fixes/1175-cw-consensus-state-height-iteration-codec.md b/.changelog/unreleased/bug-fixes/1175-cw-consensus-state-height-iteration-codec.md index 30f2793da..1b8e3098f 100644 --- a/.changelog/unreleased/bug-fixes/1175-cw-consensus-state-height-iteration-codec.md +++ b/.changelog/unreleased/bug-fixes/1175-cw-consensus-state-height-iteration-codec.md @@ -1,4 +1,4 @@ - [ibc-clients/cw-context] Fix `ConsensusState` height iteration. ([\#1175](https://github.com/cosmos/ibc-rs/issues/1175)) - [ibc-clients/cw-context] Encode and decode `ConsensusState` heights using - Protobuf. ([\#1176](https://github.com/cosmos/ibc-rs/issues/1176)) + Protobuf. ([\#1176](https://github.com/cosmos/ibc-rs/pull/1176)) From 7a10782973a73b931ef8b268b1f003ce0ea2ba37 Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Sat, 20 Apr 2024 11:40:34 +0200 Subject: [PATCH 09/19] rm changelog entry --- .../1175-cw-consensus-state-height-iteration-codec.md | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 .changelog/unreleased/bug-fixes/1175-cw-consensus-state-height-iteration-codec.md diff --git a/.changelog/unreleased/bug-fixes/1175-cw-consensus-state-height-iteration-codec.md b/.changelog/unreleased/bug-fixes/1175-cw-consensus-state-height-iteration-codec.md deleted file mode 100644 index 1b8e3098f..000000000 --- a/.changelog/unreleased/bug-fixes/1175-cw-consensus-state-height-iteration-codec.md +++ /dev/null @@ -1,4 +0,0 @@ -- [ibc-clients/cw-context] Fix `ConsensusState` height iteration. - ([\#1175](https://github.com/cosmos/ibc-rs/issues/1175)) -- [ibc-clients/cw-context] Encode and decode `ConsensusState` heights using - Protobuf. ([\#1176](https://github.com/cosmos/ibc-rs/pull/1176)) From 5133dfbe968d8922dc5d489de012e27db3e46db3 Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Sat, 20 Apr 2024 11:44:41 +0200 Subject: [PATCH 10/19] handle missing case --- ibc-clients/cw-context/src/context/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ibc-clients/cw-context/src/context/mod.rs b/ibc-clients/cw-context/src/context/mod.rs index 312347852..4eeb5c32c 100644 --- a/ibc-clients/cw-context/src/context/mod.rs +++ b/ibc-clients/cw-context/src/context/mod.rs @@ -215,7 +215,8 @@ impl<'a, C: ClientType<'a>> Context<'a, C> { let iterator = self .storage_ref() - .range(Some(&start_key), None, Order::Ascending); + .range(Some(&start_key), None, Order::Ascending) + .filter(|(key, _)| key.starts_with(ITERATE_CONSENSUS_STATE_PREFIX.as_bytes())); for (key, height) in iterator { metadata.push(GenesisMetadata { key, value: height }); From 9c76cc8f26e6374e5bf69289a7f8aeff4a29cfc4 Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Sat, 20 Apr 2024 12:30:11 +0200 Subject: [PATCH 11/19] use cw_storage_plus::Map --- Cargo.toml | 1 + ibc-clients/cw-context/Cargo.toml | 1 + 2 files changed, 2 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index b85c7e0c1..62981c026 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -119,6 +119,7 @@ tendermint-testgen = { version = "0.34.0", default-features = fals cosmwasm-schema = { version = "1.5.2" } cosmwasm-std = { version = "1.5.2" } cosmwasm-vm = { version = "1.5.2" } +cw-storage-plus = { version = "1.2.0" } # parity dependencies parity-scale-codec = { version = "3.6.5", default-features = false, features = ["full"] } diff --git a/ibc-clients/cw-context/Cargo.toml b/ibc-clients/cw-context/Cargo.toml index c3fd8ecb5..95132d252 100644 --- a/ibc-clients/cw-context/Cargo.toml +++ b/ibc-clients/cw-context/Cargo.toml @@ -28,6 +28,7 @@ ibc-client-wasm-types = { workspace = true, features = ["cosmwasm"] } # cosmwasm dependencies cosmwasm-schema = { workspace = true } cosmwasm-std = { workspace = true } +cw-storage-plus = { workspace = true } [features] default = ["std"] From edcaab30499110f87b8d1631b86d9adaf4e331c6 Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Sat, 20 Apr 2024 12:31:36 +0200 Subject: [PATCH 12/19] store or delete height keys at cw_storage_plus::Map --- .../cw-context/src/context/client_ctx.rs | 27 +++++++++++-------- ibc-clients/cw-context/src/context/mod.rs | 3 +++ 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/ibc-clients/cw-context/src/context/client_ctx.rs b/ibc-clients/cw-context/src/context/client_ctx.rs index 63aad8ee3..8b76e560a 100644 --- a/ibc-clients/cw-context/src/context/client_ctx.rs +++ b/ibc-clients/cw-context/src/context/client_ctx.rs @@ -7,13 +7,13 @@ use ibc_core::client::types::error::ClientError; use ibc_core::client::types::Height; use ibc_core::handler::types::error::ContextError; use ibc_core::host::types::identifiers::ClientId; -use ibc_core::host::types::path::{iteration_key, ClientConsensusStatePath, ClientStatePath}; +use ibc_core::host::types::path::{ClientConsensusStatePath, ClientStatePath}; use ibc_core::primitives::proto::{Any, Protobuf}; use ibc_core::primitives::Timestamp; -use super::Context; +use super::{Context, StorageMut}; use crate::api::ClientType; -use crate::utils::{encode_height, AnyCodec}; +use crate::utils::AnyCodec; impl<'a, C: ClientType<'a>> ClientValidationContext for Context<'a, C> { type ClientStateRef = C::ClientState; @@ -154,11 +154,15 @@ impl<'a, C: ClientType<'a>> ClientExecutionContext for Context<'a, C> { self.insert(prefixed_height_key, revision_height_vec); - let iteration_key = iteration_key(height.revision_number(), height.revision_height()); - - let height_vec = encode_height(height); - - self.insert(iteration_key, height_vec); + super::CONSENSUS_STATE_HEIGHT_MAP + .save( + self.storage_mut(), + (height.revision_number(), height.revision_height()), + &Default::default(), + ) + .map_err(|e| ClientError::Other { + description: e.to_string(), + })?; Ok(()) } @@ -180,9 +184,10 @@ impl<'a, C: ClientType<'a>> ClientExecutionContext for Context<'a, C> { self.remove(prefixed_height_key); - let iteration_key = iteration_key(height.revision_number(), height.revision_height()); - - self.remove(iteration_key); + super::CONSENSUS_STATE_HEIGHT_MAP.remove( + self.storage_mut(), + (height.revision_number(), height.revision_height()), + ); Ok(()) } diff --git a/ibc-clients/cw-context/src/context/mod.rs b/ibc-clients/cw-context/src/context/mod.rs index 4eeb5c32c..ecfcd04fd 100644 --- a/ibc-clients/cw-context/src/context/mod.rs +++ b/ibc-clients/cw-context/src/context/mod.rs @@ -22,6 +22,9 @@ use crate::utils::{decode_height, AnyCodec}; type Checksum = Vec; +pub const CONSENSUS_STATE_HEIGHT_MAP: Map<'_, (u64, u64), Empty> = + Map::new(ITERATE_CONSENSUS_STATE_PREFIX); + /// Context is a wrapper around the deps and env that gives access to the /// methods under the ibc-rs Validation and Execution traits. pub struct Context<'a, C: ClientType<'a>> { From c6331d5e58a94cdf40fee69cdfb19b930d30a023 Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Sat, 20 Apr 2024 12:32:44 +0200 Subject: [PATCH 13/19] use cw_storage_plus::Map range or keys --- ibc-clients/cw-context/src/context/mod.rs | 77 +++++++++++++---------- 1 file changed, 44 insertions(+), 33 deletions(-) diff --git a/ibc-clients/cw-context/src/context/mod.rs b/ibc-clients/cw-context/src/context/mod.rs index ecfcd04fd..b2b126682 100644 --- a/ibc-clients/cw-context/src/context/mod.rs +++ b/ibc-clients/cw-context/src/context/mod.rs @@ -18,7 +18,9 @@ use prost::Message; use crate::api::ClientType; use crate::types::{ContractError, GenesisMetadata, HeightTravel, MigrationPrefix}; -use crate::utils::{decode_height, AnyCodec}; +use crate::utils::AnyCodec; +use cosmwasm_std::Empty; +use cw_storage_plus::{Bound, Map}; type Checksum = Vec; @@ -133,11 +135,10 @@ impl<'a, C: ClientType<'a>> Context<'a, C> { /// Returns the storage of the context. pub fn get_heights(&self) -> Result, ClientError> { - let iterator = self.storage_ref().range(None, None, Order::Ascending); - - iterator - .filter(|(key, _)| key.starts_with(ITERATE_CONSENSUS_STATE_PREFIX.as_bytes())) - .map(|(_, value)| decode_height(value)) + CONSENSUS_STATE_HEIGHT_MAP + .keys(self.storage_ref(), None, None, Order::Ascending) + .flatten() + .map(|(rev_number, rev_height)| Height::new(rev_number, rev_height)) .collect() } @@ -148,22 +149,31 @@ impl<'a, C: ClientType<'a>> Context<'a, C> { height: &Height, travel: HeightTravel, ) -> Result, ClientError> { - let iteration_key = iteration_key(height.revision_number(), height.revision_height()); - - let mut iterator = match travel { - HeightTravel::Prev => { - self.storage_ref() - .range(None, Some(&iteration_key), Order::Descending) - } - HeightTravel::Next => { - self.storage_ref() - .range(Some(&iteration_key), None, Order::Ascending) - } + let iterator = match travel { + HeightTravel::Prev => CONSENSUS_STATE_HEIGHT_MAP.range( + self.storage_ref(), + None, + Some(Bound::exclusive(( + height.revision_number(), + height.revision_height(), + ))), + Order::Descending, + ), + HeightTravel::Next => CONSENSUS_STATE_HEIGHT_MAP.range( + self.storage_ref(), + Some(Bound::exclusive(( + height.revision_number(), + height.revision_height(), + ))), + None, + Order::Ascending, + ), }; iterator - .find(|(key, _)| key.starts_with(ITERATE_CONSENSUS_STATE_PREFIX.as_bytes())) - .map(|(_, height)| decode_height(height)) + .flatten() + .map(|((rev_number, rev_height), _)| Height::new(rev_number, rev_height)) + .next() .transpose() } @@ -194,15 +204,12 @@ impl<'a, C: ClientType<'a>> Context<'a, C> { pub fn get_metadata(&self) -> Result>, ContractError> { let mut metadata = Vec::::new(); - let start_key = ITERATE_CONSENSUS_STATE_PREFIX.to_string().into_bytes(); + let iterator = CONSENSUS_STATE_HEIGHT_MAP + .keys(self.storage_ref(), None, None, Order::Ascending) + .flatten(); - let iterator = self - .storage_ref() - .range(Some(&start_key), None, Order::Ascending) - .filter(|(key, _)| key.starts_with(ITERATE_CONSENSUS_STATE_PREFIX.as_bytes())); - - for (_, encoded_height) in iterator { - let height = decode_height(encoded_height)?; + for (rev_number, rev_height) in iterator { + let height = Height::new(rev_number, rev_height)?; let processed_height_key = self.client_update_height_key(&height); metadata.push(GenesisMetadata { @@ -216,13 +223,17 @@ impl<'a, C: ClientType<'a>> Context<'a, C> { }); } - let iterator = self - .storage_ref() - .range(Some(&start_key), None, Order::Ascending) - .filter(|(key, _)| key.starts_with(ITERATE_CONSENSUS_STATE_PREFIX.as_bytes())); + let iterator = CONSENSUS_STATE_HEIGHT_MAP + .keys(self.storage_ref(), None, None, Order::Ascending) + .flatten(); + + for (rev_number, rev_height) in iterator { + let height = Height::new(rev_number, rev_height)?; - for (key, height) in iterator { - metadata.push(GenesisMetadata { key, value: height }); + metadata.push(GenesisMetadata { + key: iteration_key(rev_number, rev_height), + value: height.encode_vec(), + }); } Ok(Some(metadata)) From 7aa0c5747db544f0ff5ef809528e4ea41385a1e6 Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Sat, 20 Apr 2024 12:33:02 +0200 Subject: [PATCH 14/19] rm redundant encode_height and decode_height --- ibc-clients/cw-context/src/utils/mod.rs | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/ibc-clients/cw-context/src/utils/mod.rs b/ibc-clients/cw-context/src/utils/mod.rs index 25dd68e5f..38e96fd59 100644 --- a/ibc-clients/cw-context/src/utils/mod.rs +++ b/ibc-clients/cw-context/src/utils/mod.rs @@ -1,18 +1,3 @@ mod codec; pub use codec::*; -use ibc_core::client::types::error::ClientError; -use ibc_core::client::types::Height; -use ibc_core::primitives::proto::Protobuf; - -/// Encodes a `Height` into a Protobuf encoded byte array. -pub fn encode_height(height: Height) -> Vec { - height.encode_vec() -} - -/// Decodes a `Height` from a Protobuf encoded byte array. -pub fn decode_height(encoded_height: Vec) -> Result { - Height::decode_vec(&encoded_height).map_err(|e| ClientError::Other { - description: e.to_string(), - }) -} From b442f9304e308e8036e159cc00fa15a2be86a15a Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Sat, 20 Apr 2024 12:44:19 +0200 Subject: [PATCH 15/19] add comment --- ibc-clients/cw-context/src/context/mod.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ibc-clients/cw-context/src/context/mod.rs b/ibc-clients/cw-context/src/context/mod.rs index b2b126682..33505067d 100644 --- a/ibc-clients/cw-context/src/context/mod.rs +++ b/ibc-clients/cw-context/src/context/mod.rs @@ -24,6 +24,10 @@ use cw_storage_plus::{Bound, Map}; type Checksum = Vec; +// `Height` can not be used directly in place of `(u64, u64)` +// as it doesn't implement some cw_storage specific traits. +// Also a sorted set needs to be maintained. So the key type is set to +// [Empty](https://book.cosmwasm.com/cross-contract/map-storage.html#maps-as-sets). pub const CONSENSUS_STATE_HEIGHT_MAP: Map<'_, (u64, u64), Empty> = Map::new(ITERATE_CONSENSUS_STATE_PREFIX); From 41bed598367754ace2e001b581351e2fed86e5aa Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Sat, 20 Apr 2024 12:46:29 +0200 Subject: [PATCH 16/19] use imports --- ibc-clients/cw-context/src/context/client_ctx.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ibc-clients/cw-context/src/context/client_ctx.rs b/ibc-clients/cw-context/src/context/client_ctx.rs index 8b76e560a..acb45c311 100644 --- a/ibc-clients/cw-context/src/context/client_ctx.rs +++ b/ibc-clients/cw-context/src/context/client_ctx.rs @@ -13,6 +13,7 @@ use ibc_core::primitives::Timestamp; use super::{Context, StorageMut}; use crate::api::ClientType; +use crate::context::CONSENSUS_STATE_HEIGHT_MAP; use crate::utils::AnyCodec; impl<'a, C: ClientType<'a>> ClientValidationContext for Context<'a, C> { @@ -154,7 +155,7 @@ impl<'a, C: ClientType<'a>> ClientExecutionContext for Context<'a, C> { self.insert(prefixed_height_key, revision_height_vec); - super::CONSENSUS_STATE_HEIGHT_MAP + CONSENSUS_STATE_HEIGHT_MAP .save( self.storage_mut(), (height.revision_number(), height.revision_height()), @@ -184,7 +185,7 @@ impl<'a, C: ClientType<'a>> ClientExecutionContext for Context<'a, C> { self.remove(prefixed_height_key); - super::CONSENSUS_STATE_HEIGHT_MAP.remove( + CONSENSUS_STATE_HEIGHT_MAP.remove( self.storage_mut(), (height.revision_number(), height.revision_height()), ); From 4a4679c3149e69254b77d3f4b19a3d27c4b2cac5 Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Sat, 20 Apr 2024 12:47:00 +0200 Subject: [PATCH 17/19] cargo format --- ibc-clients/cw-context/src/context/mod.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ibc-clients/cw-context/src/context/mod.rs b/ibc-clients/cw-context/src/context/mod.rs index 33505067d..cdc36c95d 100644 --- a/ibc-clients/cw-context/src/context/mod.rs +++ b/ibc-clients/cw-context/src/context/mod.rs @@ -3,7 +3,8 @@ pub mod custom_ctx; use std::str::FromStr; -use cosmwasm_std::{Deps, DepsMut, Env, Order, Storage}; +use cosmwasm_std::{Deps, DepsMut, Empty, Env, Order, Storage}; +use cw_storage_plus::{Bound, Map}; use ibc_client_wasm_types::client_state::ClientState as WasmClientState; use ibc_core::client::context::client_state::ClientStateCommon; use ibc_core::client::types::error::ClientError; @@ -19,8 +20,6 @@ use prost::Message; use crate::api::ClientType; use crate::types::{ContractError, GenesisMetadata, HeightTravel, MigrationPrefix}; use crate::utils::AnyCodec; -use cosmwasm_std::Empty; -use cw_storage_plus::{Bound, Map}; type Checksum = Vec; From b08220060936fd8843f40b418ad2a4b08febf948 Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Sun, 21 Apr 2024 10:32:09 +0200 Subject: [PATCH 18/19] deserialized result must be handled --- ibc-clients/cw-context/src/context/mod.rs | 44 +++++++++++++++++------ 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/ibc-clients/cw-context/src/context/mod.rs b/ibc-clients/cw-context/src/context/mod.rs index cdc36c95d..068eae8f3 100644 --- a/ibc-clients/cw-context/src/context/mod.rs +++ b/ibc-clients/cw-context/src/context/mod.rs @@ -140,8 +140,13 @@ impl<'a, C: ClientType<'a>> Context<'a, C> { pub fn get_heights(&self) -> Result, ClientError> { CONSENSUS_STATE_HEIGHT_MAP .keys(self.storage_ref(), None, None, Order::Ascending) - .flatten() - .map(|(rev_number, rev_height)| Height::new(rev_number, rev_height)) + .map(|deserialized_result| { + let (rev_number, rev_height) = + deserialized_result.map_err(|e| ClientError::Other { + description: e.to_string(), + })?; + Height::new(rev_number, rev_height) + }) .collect() } @@ -174,8 +179,13 @@ impl<'a, C: ClientType<'a>> Context<'a, C> { }; iterator - .flatten() - .map(|((rev_number, rev_height), _)| Height::new(rev_number, rev_height)) + .map(|deserialized_result| { + let ((rev_number, rev_height), _) = + deserialized_result.map_err(|e| ClientError::Other { + description: e.to_string(), + })?; + Height::new(rev_number, rev_height) + }) .next() .transpose() } @@ -209,10 +219,16 @@ impl<'a, C: ClientType<'a>> Context<'a, C> { let iterator = CONSENSUS_STATE_HEIGHT_MAP .keys(self.storage_ref(), None, None, Order::Ascending) - .flatten(); + .map(|deserialized_result| { + let (rev_number, rev_height) = + deserialized_result.map_err(|e| ClientError::Other { + description: e.to_string(), + })?; + Height::new(rev_number, rev_height) + }); - for (rev_number, rev_height) in iterator { - let height = Height::new(rev_number, rev_height)?; + for height_result in iterator { + let height = height_result?; let processed_height_key = self.client_update_height_key(&height); metadata.push(GenesisMetadata { @@ -228,13 +244,19 @@ impl<'a, C: ClientType<'a>> Context<'a, C> { let iterator = CONSENSUS_STATE_HEIGHT_MAP .keys(self.storage_ref(), None, None, Order::Ascending) - .flatten(); + .map(|deserialized_result| { + let (rev_number, rev_height) = + deserialized_result.map_err(|e| ClientError::Other { + description: e.to_string(), + })?; + Height::new(rev_number, rev_height) + }); - for (rev_number, rev_height) in iterator { - let height = Height::new(rev_number, rev_height)?; + for height_result in iterator { + let height = height_result?; metadata.push(GenesisMetadata { - key: iteration_key(rev_number, rev_height), + key: iteration_key(height.revision_number(), height.revision_height()), value: height.encode_vec(), }); } From 6dc68cf01af43e064cfd2f7f92ed328dc4be2bd0 Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Sun, 21 Apr 2024 10:36:24 +0200 Subject: [PATCH 19/19] update doc string --- ibc-clients/cw-context/src/context/mod.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ibc-clients/cw-context/src/context/mod.rs b/ibc-clients/cw-context/src/context/mod.rs index 068eae8f3..1000f837c 100644 --- a/ibc-clients/cw-context/src/context/mod.rs +++ b/ibc-clients/cw-context/src/context/mod.rs @@ -23,10 +23,11 @@ use crate::utils::AnyCodec; type Checksum = Vec; -// `Height` can not be used directly in place of `(u64, u64)` -// as it doesn't implement some cw_storage specific traits. -// Also a sorted set needs to be maintained. So the key type is set to -// [Empty](https://book.cosmwasm.com/cross-contract/map-storage.html#maps-as-sets). +/// - [`Height`] can not be used directly as keys in the map, +/// as it doesn't implement some cw_storage specific traits. +/// - Only a sorted set is needed. So the value type is set to +/// [`Empty`] following +/// ([cosmwasm-book](https://book.cosmwasm.com/cross-contract/map-storage.html#maps-as-sets)). pub const CONSENSUS_STATE_HEIGHT_MAP: Map<'_, (u64, u64), Empty> = Map::new(ITERATE_CONSENSUS_STATE_PREFIX);