Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions cosmwasm/ibc-union/core/msg/src/msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,13 @@ pub enum ExecuteMsg {
PacketSend(MsgSendPacket),
WriteAcknowledgement(MsgWriteAcknowledgement),
MigrateState(MsgMigrateState),
CommitClientStatus(MsgCommitClientStatus),
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct MsgCommitClientStatus {
pub client_id: ClientId,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
Expand Down
2 changes: 2 additions & 0 deletions cosmwasm/ibc-union/core/msg/src/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ pub enum QueryMsg {
GetConsensusState { client_id: ClientId, height: u64 },
#[cfg_attr(feature = "cw-orch-interface", returns(crate::lightclient::Status))]
GetStatus { client_id: ClientId },
#[cfg_attr(feature = "cw-orch-interface", returns(crate::lightclient::Status))]
GetCommittedStatus { client_id: ClientId },
#[cfg_attr(feature = "cw-orch-interface", returns(String))]
GetClientType { client_id: ClientId },
#[cfg_attr(feature = "cw-orch-interface", returns(ibc_union_spec::Connection))]
Expand Down
31 changes: 29 additions & 2 deletions cosmwasm/ibc-union/core/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,16 @@ use ibc_union_msg::{
use ibc_union_spec::{
path::{
commit_packets, BatchPacketsPath, BatchReceiptsPath, ChannelPath, ClientStatePath,
ConnectionPath, ConsensusStatePath, COMMITMENT_MAGIC, COMMITMENT_MAGIC_ACK,
ClientStatusPath, ConnectionPath, ConsensusStatePath, COMMITMENT_MAGIC,
COMMITMENT_MAGIC_ACK,
},
Channel, ChannelId, ChannelState, ClientId, Connection, ConnectionId, ConnectionState,
MustBeZero, Packet, Status, Timestamp,
};
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use unionlabs::{
ethereum::keccak256,
primitives::{Bytes, H256},
primitives::{Bytes, H256, U256},
};

use crate::{
Expand Down Expand Up @@ -624,6 +625,23 @@ pub fn execute(
.add_attribute("relayer", relayer),
))
}
ExecuteMsg::CommitClientStatus(msg) => {
let status = query_light_client::<Status>(
deps.as_ref(),
client_impl(deps.as_ref(), msg.client_id)?,
LightClientQuery::GetStatus {
client_id: msg.client_id,
},
)?;
let key = ClientStatusPath {
client_id: msg.client_id,
}
.key();
let value = U256::from(status as u32).to_le_bytes();
let value_h256 = H256::new(value);
store_commit(deps, &key, &value_h256);
Ok(Response::default())
}
}
}

Expand Down Expand Up @@ -2186,6 +2204,15 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> Result<Binary, ContractErr
)?;
Ok(to_json_binary(&status)?)
}
QueryMsg::GetCommittedStatus { client_id } => {
let commit = read_commit(deps, &ClientStatusPath { client_id }.key())
.ok_or(ContractError::CommittedClientStatusNotFound { client_id })?;
let commit_bytes: [u8; 32] = *commit.get();
let u256 = U256::from_le_bytes(commit_bytes);
let status = Status::try_from(u256)
.map_err(|err| ContractError::InvalidClientStatusValue { value: err.value })?;
Ok(to_json_binary(&status)?)
}
QueryMsg::GetChannels { contract } => {
let contract = deps.api.addr_validate(&contract)?;
let channels = deps.storage.read::<ContractChannels>(&contract)?;
Expand Down
10 changes: 10 additions & 0 deletions cosmwasm/ibc-union/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,16 @@ pub enum ContractError {
OnlyWhitelistedRelayer,
#[error("sender is not the relayer admin")]
OnlyRelayerAdmin,
#[error(
"{} committed client status not found for client id {client_id}",
ContractErrorKind::from(self)
)]
CommittedClientStatusNotFound { client_id: ClientId },
#[error(
"{} invalid committed status value: {value}",
ContractErrorKind::from(self)
)]
InvalidClientStatusValue { value: u8 },
}

impl ContractErrorKind {
Expand Down
32 changes: 31 additions & 1 deletion lib/ibc-union-spec/src/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use voyager_primitives::IbcStorePathKey;
use crate::Packet;
use crate::{
types::{ChannelId, ClientId, ConnectionId},
Channel, Connection, IbcUnion,
Channel, Connection, IbcUnion, Status,
};

pub const IBC_UNION_COSMWASM_COMMITMENT_PREFIX: [u8; 1] = [0x00];
Expand All @@ -34,6 +34,7 @@ pub const CONNECTIONS: U256 = U256::from_limbs([2, 0, 0, 0]);
pub const CHANNELS: U256 = U256::from_limbs([3, 0, 0, 0]);
pub const PACKETS: U256 = U256::from_limbs([4, 0, 0, 0]);
pub const PACKET_ACKS: U256 = U256::from_limbs([5, 0, 0, 0]);
pub const CLIENT_STATUS: U256 = U256::from_limbs([6, 0, 0, 0]);

#[cfg(feature = "ethabi")]
#[must_use]
Expand All @@ -60,6 +61,7 @@ pub enum StorePath {
Channel(ChannelPath),
BatchReceipts(BatchReceiptsPath),
BatchPackets(BatchPacketsPath),
ClientStatus(ClientStatusPath),
}

impl StorePath {
Expand All @@ -72,6 +74,7 @@ impl StorePath {
StorePath::Channel(path) => path.key(),
StorePath::BatchReceipts(path) => path.key(),
StorePath::BatchPackets(path) => path.key(),
StorePath::ClientStatus(path) => path.key(),
}
}
}
Expand Down Expand Up @@ -265,3 +268,30 @@ impl IbcStorePathKey for BatchPacketsPath {

type Value = H256;
}

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(rename_all = "snake_case", deny_unknown_fields)
)]
pub struct ClientStatusPath {
pub client_id: ClientId,
}

impl ClientStatusPath {
#[must_use]
pub fn key(&self) -> H256 {
Keccak256::new()
.chain_update(CLIENT_STATUS.to_be_bytes())
.chain_update(U256::from(self.client_id.get()).to_be_bytes())
.finalize()
.into()
}
}

impl IbcStorePathKey for ClientStatusPath {
type Spec = IbcUnion;
type Value = Status;
}
29 changes: 28 additions & 1 deletion lib/ibc-union-spec/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ macro_rules! id {
id.raw().into()
}
}

impl From<NonZeroU32> for $T {
fn from(id: NonZeroU32) -> Self {
<$T>::new(id)
Expand Down Expand Up @@ -96,6 +95,7 @@ id!(ChannelId);
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
#[serde(deny_unknown_fields, rename_all = "snake_case")]
#[repr(u8)]
pub enum Status {
Active = 1,
Expired = 2,
Expand All @@ -111,3 +111,30 @@ impl fmt::Display for Status {
})
}
}

#[derive(Debug, Clone, PartialEq)]
pub struct UnknownEnumVariant {
pub value: u8,
}
Comment on lines +115 to +118
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't redefine this, reuse it from unionlabs


impl TryFrom<u8> for Status {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also add a TryFrom<U256> impl

type Error = UnknownEnumVariant;

fn try_from(value: u8) -> Result<Self, Self::Error> {
match value {
1 => Ok(Status::Active),
2 => Ok(Status::Expired),
3 => Ok(Status::Frozen),
_ => Err(UnknownEnumVariant { value }),
}
}
}

impl TryFrom<U256> for Status {
type Error = UnknownEnumVariant;

fn try_from(value: U256) -> Result<Self, Self::Error> {
let byte = value.to_le_bytes()[0];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this drops the majority of the u256. implement this correctly

Status::try_from(byte)
}
}
27 changes: 27 additions & 0 deletions voyager/modules/state/cosmos-sdk-union/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,29 @@ impl Module {

Ok(commitment.flatten())
}

#[instrument(
skip_all,
fields(
chain_id = %self.chain_id,
%height,
%client_id
)
)]
async fn query_committed_client_status(
&self,
height: Height,
client_id: ClientId,
) -> RpcResult<Option<Status>> {
let commitment = self
.query_smart::<_, Option<Status>>(
&ibc_union_msg::query::QueryMsg::GetCommittedStatus { client_id },
Some(height),
)
.await?;

Ok(commitment.flatten())
}
}

#[derive(Debug, thiserror::Error)]
Expand Down Expand Up @@ -526,6 +549,10 @@ impl StateModuleServer<IbcUnion> for Module {
.query_batch_receipts(at, path.batch_hash)
.await
.map(into_value),
StorePath::ClientStatus(path) => self
.query_committed_client_status(at, path.client_id)
.await
.map(into_value),
}
}
}
Expand Down
13 changes: 13 additions & 0 deletions voyager/modules/state/ethereum/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,15 @@ impl Module {
)),
}
}

#[instrument(skip_all,fields(chain_id = %self.chain_id, %height, %client_id))]
async fn query_committed_client_status(
&self,
height: Height,
client_id: ClientId,
) -> RpcResult<Option<Status>> {
unimplemented!("query_client_status is not implemented yet");
}
}

fn mk_windows(mut latest_height: u64, window: u64) -> Vec<(BlockNumberOrTag, BlockNumberOrTag)> {
Expand Down Expand Up @@ -704,6 +713,10 @@ impl StateModuleServer<IbcUnion> for Module {
.query_batch_packets(at, path.batch_hash)
.await
.map(into_value),
StorePath::ClientStatus(path) => self
.query_committed_client_status(at, path.client_id)
.await
.map(into_value),
}
}

Expand Down