Skip to content

Commit 8e70297

Browse files
committed
feat(lightclient): add CommitClientStatus message to persist client status
1 parent 0763bf0 commit 8e70297

File tree

9 files changed

+131
-13
lines changed

9 files changed

+131
-13
lines changed

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

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,6 @@ use std::collections::BTreeMap;
33
use ibc_union_spec::ClientId;
44
use unionlabs_primitives::Bytes;
55

6-
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
7-
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
8-
#[serde(deny_unknown_fields, rename_all = "snake_case")]
9-
pub enum Status {
10-
Active,
11-
Expired,
12-
Frozen,
13-
}
14-
156
#[derive(serde::Serialize, serde::Deserialize)]
167
#[serde(deny_unknown_fields, rename_all = "snake_case")]
178
pub struct MisbehaviourResponse {

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

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

5562
#[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, height: u64 },
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: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use depolama::{RawStore, StorageExt};
1111
use frissitheto::{UpgradeError, UpgradeMsg};
1212
use ibc_union_msg::{
1313
lightclient::{
14-
QueryMsg as LightClientQuery, Status, UpdateStateResponse, VerifyCreationResponse,
14+
QueryMsg as LightClientQuery, UpdateStateResponse, VerifyCreationResponse,
1515
VerifyCreationResponseEvent,
1616
},
1717
module::{ExecuteMsg as ModuleMsg, IbcUnionMsg},
@@ -28,7 +28,8 @@ use ibc_union_msg::{
2828
use ibc_union_spec::{
2929
path::{
3030
commit_packets, BatchPacketsPath, BatchReceiptsPath, ChannelPath, ClientStatePath,
31-
ConnectionPath, ConsensusStatePath, COMMITMENT_MAGIC, COMMITMENT_MAGIC_ACK,
31+
ClientStatusPath, ConnectionPath, ConsensusStatePath, COMMITMENT_MAGIC,
32+
COMMITMENT_MAGIC_ACK, Status,
3233
},
3334
Channel, ChannelId, ChannelState, ClientId, Connection, ConnectionId, ConnectionState, Packet,
3435
Timestamp,
@@ -596,6 +597,28 @@ pub fn execute(
596597
.add_attribute("relayer", relayer),
597598
))
598599
}
600+
ExecuteMsg::CommitClientStatus(msg) => {
601+
let status = query_light_client::<Status>(
602+
deps.as_ref(),
603+
client_impl(deps.as_ref(), msg.client_id)?,
604+
LightClientQuery::GetStatus {
605+
client_id: msg.client_id,
606+
},
607+
)?;
608+
609+
let status_bytes = (status as u8).to_le_bytes();
610+
611+
store_commit(
612+
deps.branch(),
613+
&ClientStatusPath {
614+
client_id: msg.client_id,
615+
}
616+
.key(),
617+
&commit(status_bytes),
618+
);
619+
620+
Ok(Response::default())
621+
}
599622
}
600623
}
601624

@@ -2171,6 +2194,10 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> Result<Binary, ContractErr
21712194
)?;
21722195
Ok(to_json_binary(&status)?)
21732196
}
2197+
QueryMsg::GetCommittedStatus { client_id, .. } => {
2198+
let commit = read_commit(deps, &ClientStatusPath { client_id }.key());
2199+
Ok(to_json_binary(&commit)?)
2200+
}
21742201
QueryMsg::GetChannels { contract } => {
21752202
let contract = deps.api.addr_validate(&contract)?;
21762203
let channels = deps.storage.read::<ContractChannels>(&contract)?;

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ mod tests;
1010

1111
use cosmwasm_std::{Addr, StdError};
1212
use frissitheto::UpgradeError;
13-
use ibc_union_msg::lightclient::Status;
13+
use ibc_union_spec::path::Status;
1414
use ibc_union_spec::{ChannelId, ChannelState, ClientId, ConnectionState, Timestamp};
1515
use thiserror::Error;
1616
use unionlabs::primitives::Bytes;

lib/ibc-union-spec/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ voyager-primitives = { workspace = true }
2828
ibc-union-spec = { workspace = true, features = ["ethabi", "schemars", "serde"] }
2929

3030
[features]
31-
default = []
31+
default = ["serde"]
3232

3333
bincode = ["dep:bincode", "voyager-primitives/bincode", "unionlabs/bincode"]
3434
ethabi = ["dep:alloy-sol-types", "unionlabs/ethabi"]

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

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use sha3::{Digest, Keccak256};
33
use unionlabs::primitives::{Bytes, H256, U256};
44
use voyager_primitives::IbcStorePathKey;
55

6+
67
#[cfg(feature = "ethabi")]
78
use crate::Packet;
89
use crate::{
@@ -34,6 +35,7 @@ pub const CONNECTIONS: U256 = U256::from_limbs([2, 0, 0, 0]);
3435
pub const CHANNELS: U256 = U256::from_limbs([3, 0, 0, 0]);
3536
pub const PACKETS: U256 = U256::from_limbs([4, 0, 0, 0]);
3637
pub const PACKET_ACKS: U256 = U256::from_limbs([5, 0, 0, 0]);
38+
pub const CLIENT_STATUS: U256 = U256::from_limbs([6, 0, 0, 0]);
3739

3840
#[cfg(feature = "ethabi")]
3941
#[must_use]
@@ -60,6 +62,7 @@ pub enum StorePath {
6062
Channel(ChannelPath),
6163
BatchReceipts(BatchReceiptsPath),
6264
BatchPackets(BatchPacketsPath),
65+
ClientStatus(ClientStatusPath),
6366
}
6467

6568
impl StorePath {
@@ -72,6 +75,7 @@ impl StorePath {
7275
StorePath::Channel(path) => path.key(),
7376
StorePath::BatchReceipts(path) => path.key(),
7477
StorePath::BatchPackets(path) => path.key(),
78+
StorePath::ClientStatus(path) => path.key(),
7579
}
7680
}
7781
}
@@ -265,3 +269,41 @@ impl IbcStorePathKey for BatchPacketsPath {
265269

266270
type Value = H256;
267271
}
272+
273+
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
274+
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
275+
#[serde(deny_unknown_fields, rename_all = "snake_case")]
276+
#[repr(u8)]
277+
pub enum Status {
278+
Active = 1,
279+
Expired = 2,
280+
Frozen = 3,
281+
}
282+
283+
/// Represents the path to a client's committed status (Active, Expired, etc.)
284+
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
285+
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
286+
#[cfg_attr(
287+
feature = "serde",
288+
derive(serde::Serialize, serde::Deserialize),
289+
serde(rename_all = "snake_case", deny_unknown_fields)
290+
)]
291+
pub struct ClientStatusPath {
292+
pub client_id: ClientId,
293+
}
294+
295+
impl ClientStatusPath {
296+
#[must_use]
297+
pub fn key(&self) -> H256 {
298+
Keccak256::new()
299+
.chain_update(CLIENT_STATUS.to_be_bytes())
300+
.chain_update(U256::from(self.client_id.get()).to_be_bytes())
301+
.finalize()
302+
.into()
303+
}
304+
}
305+
306+
impl IbcStorePathKey for ClientStatusPath {
307+
type Spec = IbcUnion;
308+
type Value = u8; // repr(u8) status stored as raw byte
309+
}

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

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,30 @@ impl Module {
367367

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

372396
#[derive(Debug, thiserror::Error)]
@@ -503,6 +527,10 @@ impl StateModuleServer<IbcUnion> for Module {
503527
.query_batch_receipts(at, path.batch_hash)
504528
.await
505529
.map(into_value),
530+
StorePath::ClientStatus(path) => self
531+
.query_client_status(at, path.client_id)
532+
.await
533+
.map(into_value),
506534
}
507535
}
508536
}

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,23 @@ impl Module {
566566
None::<()>,
567567
))
568568
}
569+
570+
#[instrument(skip_all,fields(chain_id = %self.chain_id, %height, %client_id))]
571+
async fn query_client_status(
572+
&self,
573+
height: Height,
574+
client_id: ClientId,
575+
) -> RpcResult<Option<u8>> {
576+
let status = self
577+
.query_smart::<_, u8>(
578+
&ibc_union_msg::query::QueryMsg::GetStatus { client_id },
579+
Some(height),
580+
)
581+
.await?;
582+
583+
Ok(status)
584+
}
585+
569586
}
570587

571588
fn mk_windows(mut latest_height: u64, window: u64) -> Vec<(BlockNumberOrTag, BlockNumberOrTag)> {
@@ -633,6 +650,10 @@ impl StateModuleServer<IbcUnion> for Module {
633650
.query_batch_packets(at, path.batch_hash)
634651
.await
635652
.map(into_value),
653+
StorePath::ClientStatus(path) => self
654+
.query_client_status(at, path.client_id)
655+
.await
656+
.map(into_value),
636657
}
637658
}
638659

0 commit comments

Comments
 (0)