Skip to content

Commit b3cb34c

Browse files
committed
feat: add committed status query/store for lightclients
1 parent 75a1a1f commit b3cb34c

File tree

8 files changed

+103
-4
lines changed

8 files changed

+103
-4
lines changed

cosmwasm/ibc-union/core/msg/src/msg.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,13 @@ pub enum ExecuteMsg {
5151
PacketSend(MsgSendPacket),
5252
WriteAcknowledgement(MsgWriteAcknowledgement),
5353
MigrateState(MsgMigrateState),
54+
CommitClientStatus(MsgCommitClientStatus),
55+
}
56+
57+
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
58+
#[serde(deny_unknown_fields)]
59+
pub struct MsgCommitClientStatus {
60+
pub client_id: ClientId,
5461
}
5562

5663
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]

cosmwasm/ibc-union/core/msg/src/query.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ pub enum QueryMsg {
1818
GetConsensusState { client_id: ClientId, height: u64 },
1919
#[cfg_attr(feature = "cw-orch-interface", returns(crate::lightclient::Status))]
2020
GetStatus { client_id: ClientId },
21+
#[cfg_attr(feature = "cw-orch-interface", returns(crate::lightclient::Status))]
22+
GetCommittedStatus { client_id: ClientId },
2123
#[cfg_attr(feature = "cw-orch-interface", returns(String))]
2224
GetClientType { client_id: ClientId },
2325
#[cfg_attr(feature = "cw-orch-interface", returns(ibc_union_spec::Connection))]

cosmwasm/ibc-union/core/src/contract.rs

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,15 @@ use ibc_union_spec::{
3636
use serde::{de::DeserializeOwned, Deserialize, Serialize};
3737
use unionlabs::{
3838
ethereum::keccak256,
39-
primitives::{Bytes, H256},
39+
primitives::{Bytes, H256, U256},
4040
};
4141

4242
use crate::{
4343
state::{
4444
ChannelOwner, Channels, ClientConsensusStates, ClientImpls, ClientRegistry, ClientStates,
45-
ClientStore, ClientTypes, Commitments, Connections, ContractChannels, NextChannelId,
46-
NextClientId, NextConnectionId, QueryStore, WhitelistedRelayers, WhitelistedRelayersAdmin,
45+
ClientStatuses, ClientStore, ClientTypes, Commitments, Connections, ContractChannels,
46+
NextChannelId, NextClientId, NextConnectionId, QueryStore, WhitelistedRelayers,
47+
WhitelistedRelayersAdmin,
4748
},
4849
ContractError,
4950
};
@@ -624,6 +625,19 @@ pub fn execute(
624625
.add_attribute("relayer", relayer),
625626
))
626627
}
628+
ExecuteMsg::CommitClientStatus(msg) => {
629+
let status = query_light_client::<Status>(
630+
deps.as_ref(),
631+
client_impl(deps.as_ref(), msg.client_id)?,
632+
LightClientQuery::GetStatus {
633+
client_id: msg.client_id,
634+
},
635+
)?;
636+
let encoded = U256::from(status as u32);
637+
deps.storage
638+
.write::<ClientStatuses>(&msg.client_id, &encoded);
639+
Ok(Response::default())
640+
}
627641
}
628642
}
629643

@@ -2186,6 +2200,13 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> Result<Binary, ContractErr
21862200
)?;
21872201
Ok(to_json_binary(&status)?)
21882202
}
2203+
QueryMsg::GetCommittedStatus { client_id } => {
2204+
let val = deps.storage.read::<ClientStatuses>(&client_id)?;
2205+
let raw = val.to_le_bytes()[0];
2206+
let status = Status::try_from(raw)
2207+
.map_err(|_| ContractError::InvalidClientStatusValue { value: raw as u32 })?;
2208+
Ok(to_json_binary(&status)?)
2209+
}
21892210
QueryMsg::GetChannels { contract } => {
21902211
let contract = deps.api.addr_validate(&contract)?;
21912212
let channels = deps.storage.read::<ContractChannels>(&contract)?;

cosmwasm/ibc-union/core/src/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,11 @@ pub enum ContractError {
158158
OnlyWhitelistedRelayer,
159159
#[error("sender is not the relayer admin")]
160160
OnlyRelayerAdmin,
161+
#[error(
162+
"{} invalid committed status value: {value}",
163+
ContractErrorKind::from(self)
164+
)]
165+
InvalidClientStatusValue { value: u32 },
161166
}
162167

163168
impl ContractErrorKind {

cosmwasm/ibc-union/core/src/state.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use depolama::{value::ValueCodecViaEncoding, KeyCodec, Prefix, Store, ValueCodec
55
use ibc_union_spec::{Channel, ChannelId, ClientId, Connection, ConnectionId};
66
use unionlabs::{
77
encoding::Bincode,
8-
primitives::{ByteArrayExt, Bytes, H256},
8+
primitives::{ByteArrayExt, Bytes, H256, U256},
99
};
1010

1111
macro_rules! id_key {
@@ -174,6 +174,24 @@ impl Store for ClientStates {
174174
id_key!(ClientStates);
175175
bytes_value!(ClientStates);
176176

177+
pub enum ClientStatuses {}
178+
impl Store for ClientStatuses {
179+
const PREFIX: Prefix = Prefix::new(b"client_status");
180+
181+
type Key = ClientId;
182+
type Value = U256;
183+
}
184+
id_key!(ClientStatuses);
185+
impl ValueCodec<U256> for ClientStatuses {
186+
fn encode_value(value: &U256) -> Bytes {
187+
value.to_le_bytes().into()
188+
}
189+
190+
fn decode_value(raw: &Bytes) -> StdResult<U256> {
191+
read_fixed_bytes(raw).map(U256::from_le_bytes)
192+
}
193+
}
194+
177195
pub enum ClientConsensusStates {}
178196
impl Store for ClientConsensusStates {
179197
const PREFIX: Prefix = Prefix::new(b"client_consensus_states");

lib/ibc-union-spec/src/types.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ id!(ChannelId);
9696
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
9797
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
9898
#[serde(deny_unknown_fields, rename_all = "snake_case")]
99+
#[repr(u8)]
99100
pub enum Status {
100101
Active = 1,
101102
Expired = 2,
@@ -111,3 +112,16 @@ impl fmt::Display for Status {
111112
})
112113
}
113114
}
115+
116+
impl TryFrom<u8> for Status {
117+
type Error = &'static str;
118+
119+
fn try_from(value: u8) -> Result<Self, Self::Error> {
120+
match value {
121+
1 => Ok(Status::Active),
122+
2 => Ok(Status::Expired),
123+
3 => Ok(Status::Frozen),
124+
_ => Err("Invalid status value"),
125+
}
126+
}
127+
}

voyager/modules/state/cosmos-sdk-union/src/main.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,29 @@ impl Module {
368368

369369
Ok(commitment.flatten())
370370
}
371+
372+
#[instrument(
373+
skip_all,
374+
fields(
375+
chain_id = %self.chain_id,
376+
%height,
377+
%client_id
378+
)
379+
)]
380+
async fn query_committed_client_status(
381+
&self,
382+
height: Height,
383+
client_id: ClientId,
384+
) -> RpcResult<Option<Status>> {
385+
let commitment = self
386+
.query_smart::<_, Option<Status>>(
387+
&ibc_union_msg::query::QueryMsg::GetCommittedStatus { client_id },
388+
Some(height),
389+
)
390+
.await?;
391+
392+
Ok(commitment.flatten())
393+
}
371394
}
372395

373396
#[derive(Debug, thiserror::Error)]

voyager/modules/state/ethereum/src/main.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,15 @@ impl Module {
623623
)),
624624
}
625625
}
626+
627+
#[instrument(skip_all,fields(chain_id = %self.chain_id, %height, %client_id))]
628+
async fn query_committed_client_status(
629+
&self,
630+
height: Height,
631+
client_id: ClientId,
632+
) -> RpcResult<Option<Status>> {
633+
unimplemented!("query_client_status is not implemented yet");
634+
}
626635
}
627636

628637
fn mk_windows(mut latest_height: u64, window: u64) -> Vec<(BlockNumberOrTag, BlockNumberOrTag)> {

0 commit comments

Comments
 (0)