From a56859d69582f0fb898ca012fd60cee7835357c6 Mon Sep 17 00:00:00 2001 From: srdtrk Date: Wed, 11 Dec 2024 12:46:43 +0800 Subject: [PATCH] docs: fully linted and documented wasm client --- programs/cw-ics08-wasm-eth/README.md | 4 +- programs/cw-ics08-wasm-eth/src/contract.rs | 259 ++++++++++-------- .../cw-ics08-wasm-eth/src/custom_query.rs | 21 +- programs/cw-ics08-wasm-eth/src/error.rs | 9 + programs/cw-ics08-wasm-eth/src/lib.rs | 8 +- programs/cw-ics08-wasm-eth/src/msg.rs | 70 ++++- programs/cw-ics08-wasm-eth/src/state.rs | 33 ++- 7 files changed, 272 insertions(+), 132 deletions(-) diff --git a/programs/cw-ics08-wasm-eth/README.md b/programs/cw-ics08-wasm-eth/README.md index c9f82020..afbd3326 100644 --- a/programs/cw-ics08-wasm-eth/README.md +++ b/programs/cw-ics08-wasm-eth/README.md @@ -1,9 +1,9 @@ -# CosmWasm ICS08 Wasm Ethereum Light Client +# `CosmWasm` ICS08 Wasm Ethereum Light Client > [!CAUTION] > ⚠ The Ethereum Light Client is currently under heavy development, and is not ready for use. -This is the CosmWasm implementation that can be used with ibc-go's `08-wasm` light client wrapper. +This is the `CosmWasm` implementation that can be used with ibc-go's `08-wasm` light client wrapper. It handles the client and consensus state, and calls into `packages/ethereum-light-client` for all the light client related logic. ## Acknowledgements diff --git a/programs/cw-ics08-wasm-eth/src/contract.rs b/programs/cw-ics08-wasm-eth/src/contract.rs index 34d47310..cf10489b 100644 --- a/programs/cw-ics08-wasm-eth/src/contract.rs +++ b/programs/cw-ics08-wasm-eth/src/contract.rs @@ -1,3 +1,5 @@ +//! This module handles the execution logic of the contract. + use std::convert::Into; use cosmwasm_std::{ @@ -18,18 +20,18 @@ use ibc_proto::{ }; use prost::Message; -use crate::custom_query::{BlsVerifier, EthereumCustomQuery}; -use crate::error::ContractError; -use crate::msg::{ - CheckForMisbehaviourResult, ExecuteMsg, Height, InstantiateMsg, QueryMsg, StatusResult, - SudoMsg, TimestampAtHeightResult, UpdateStateResult, VerifyClientMessageMsg, - VerifyMembershipMsg, VerifyNonMembershipMsg, -}; +use crate::custom_query::EthereumCustomQuery; +use crate::msg::{ExecuteMsg, Height, InstantiateMsg, QueryMsg, SudoMsg}; use crate::state::{ consensus_db_key, get_eth_client_state, get_eth_consensus_state, HOST_CLIENT_STATE_KEY, }; +use crate::ContractError; +/// The instantiate entry point for the CosmWasm contract. +/// # Errors +/// Will return an error if the client state or consensus state cannot be deserialized. #[entry_point] +#[allow(clippy::needless_pass_by_value)] pub fn instantiate( deps: DepsMut, _env: Env, @@ -47,7 +49,7 @@ pub fn instantiate( revision_height: client_state.latest_slot, }), }; - let wasm_client_state_any = Any::from_msg(&wasm_client_state).unwrap(); + let wasm_client_state_any = Any::from_msg(&wasm_client_state)?; deps.storage.set( HOST_CLIENT_STATE_KEY.as_bytes(), wasm_client_state_any.encode_to_vec().as_slice(), @@ -59,7 +61,7 @@ pub fn instantiate( let wasm_consensus_state = WasmConsensusState { data: consensus_state_bz, }; - let wasm_consensus_state_any = Any::from_msg(&wasm_consensus_state).unwrap(); + let wasm_consensus_state_any = Any::from_msg(&wasm_consensus_state)?; let height = Height { revision_number: 0, revision_height: consensus_state.slot, @@ -72,7 +74,12 @@ pub fn instantiate( Ok(Response::default()) } +/// The sudo entry point for the CosmWasm contract. +/// It routes the message to the appropriate handler. +/// # Errors +/// Will return an error if the handler returns an error. #[entry_point] +#[allow(clippy::needless_pass_by_value)] pub fn sudo( deps: DepsMut, _env: Env, @@ -80,12 +87,12 @@ pub fn sudo( ) -> Result { let result = match msg { SudoMsg::VerifyMembership(verify_membership_msg) => { - verify_membership(deps.as_ref(), verify_membership_msg)? + sudo::verify_membership(deps.as_ref(), verify_membership_msg)? } SudoMsg::VerifyNonMembership(verify_non_membership_msg) => { - verify_non_membership(deps.as_ref(), verify_non_membership_msg)? + sudo::verify_non_membership(deps.as_ref(), verify_non_membership_msg)? } - SudoMsg::UpdateState(_) => update_state()?, + SudoMsg::UpdateState(_) => sudo::update_state()?, SudoMsg::UpdateStateOnMisbehaviour(_) => todo!(), SudoMsg::VerifyUpgradeAndUpdateState(_) => todo!(), SudoMsg::MigrateClientStore(_) => todo!(), @@ -94,59 +101,72 @@ pub fn sudo( Ok(Response::default().set_data(result)) } -pub fn verify_membership( - deps: Deps, - verify_membership_msg: VerifyMembershipMsg, -) -> Result { - let eth_client_state = get_eth_client_state(deps); - let eth_consensus_state = get_eth_consensus_state(deps, &verify_membership_msg.height); - - ethereum_light_client::membership::verify_membership( - eth_consensus_state, - eth_client_state, - verify_membership_msg.proof.into(), - verify_membership_msg - .merkle_path - .key_path - .into_iter() - .map(Into::into) - .collect(), - Some(verify_membership_msg.value.into()), - ) - .map_err(ContractError::VerifyMembershipFailed)?; - - Ok(to_json_binary(&Ok::<(), ()>(()))?) -} +mod sudo { + use crate::msg::{UpdateStateResult, VerifyMembershipMsg, VerifyNonMembershipMsg}; -pub fn verify_non_membership( - deps: Deps, - verify_non_membership_msg: VerifyNonMembershipMsg, -) -> Result { - let eth_client_state = get_eth_client_state(deps); - let eth_consensus_state = get_eth_consensus_state(deps, &verify_non_membership_msg.height); - - ethereum_light_client::membership::verify_membership( - eth_consensus_state, - eth_client_state, - verify_non_membership_msg.proof.into(), - verify_non_membership_msg - .merkle_path - .key_path - .into_iter() - .map(Into::into) - .collect(), - None, - ) - .map_err(ContractError::VerifyNonMembershipFailed)?; - - Ok(to_json_binary(&Ok::<(), ()>(()))?) -} + use super::{ + get_eth_client_state, get_eth_consensus_state, to_json_binary, Binary, ContractError, Deps, + EthereumCustomQuery, + }; + + pub fn verify_membership( + deps: Deps, + verify_membership_msg: VerifyMembershipMsg, + ) -> Result { + let eth_client_state = get_eth_client_state(deps.storage); + let eth_consensus_state = + get_eth_consensus_state(deps.storage, &verify_membership_msg.height); + + ethereum_light_client::membership::verify_membership( + eth_consensus_state, + eth_client_state, + verify_membership_msg.proof.into(), + verify_membership_msg + .merkle_path + .key_path + .into_iter() + .map(Into::into) + .collect(), + Some(verify_membership_msg.value.into()), + ) + .map_err(ContractError::VerifyMembershipFailed)?; + + Ok(to_json_binary(&Ok::<(), ()>(()))?) + } + + pub fn verify_non_membership( + deps: Deps, + verify_non_membership_msg: VerifyNonMembershipMsg, + ) -> Result { + let eth_client_state = get_eth_client_state(deps.storage); + let eth_consensus_state = + get_eth_consensus_state(deps.storage, &verify_non_membership_msg.height); + + ethereum_light_client::membership::verify_membership( + eth_consensus_state, + eth_client_state, + verify_non_membership_msg.proof.into(), + verify_non_membership_msg + .merkle_path + .key_path + .into_iter() + .map(Into::into) + .collect(), + None, + ) + .map_err(ContractError::VerifyNonMembershipFailed)?; + + Ok(to_json_binary(&Ok::<(), ()>(()))?) + } -pub fn update_state() -> Result { - Ok(to_json_binary(&UpdateStateResult { heights: vec![] })?) + pub fn update_state() -> Result { + Ok(to_json_binary(&UpdateStateResult { heights: vec![] })?) + } } +/// Execute entry point is not used in this contract. #[entry_point] +#[allow(clippy::needless_pass_by_value, clippy::missing_errors_doc)] pub fn execute( _deps: DepsMut, _env: Env, @@ -156,6 +176,10 @@ pub fn execute( unimplemented!() } +/// The query entry point for the CosmWasm contract. +/// It routes the message to the appropriate handler. +/// # Errors +/// Will return an error if the handler returns an error. #[entry_point] pub fn query( deps: Deps, @@ -164,58 +188,75 @@ pub fn query( ) -> Result { match msg { QueryMsg::VerifyClientMessage(verify_client_message_msg) => { - verify_client_message(deps, env, verify_client_message_msg) + query::verify_client_message(deps, env, verify_client_message_msg) } - QueryMsg::CheckForMisbehaviour(_) => check_for_misbehaviour(), - QueryMsg::TimestampAtHeight(_) => timestamp_at_height(env), - QueryMsg::Status(_) => status(), + QueryMsg::CheckForMisbehaviour(_) => query::check_for_misbehaviour(), + QueryMsg::TimestampAtHeight(_) => query::timestamp_at_height(env), + QueryMsg::Status(_) => query::status(), } } -pub fn verify_client_message( - deps: Deps, - env: Env, - verify_client_message_msg: VerifyClientMessageMsg, -) -> Result { - let eth_client_state = get_eth_client_state(deps); - let eth_consensus_state = get_eth_consensus_state( - deps, - &Height { - revision_number: 0, - revision_height: eth_client_state.latest_slot, +mod query { + use crate::{ + custom_query::BlsVerifier, + msg::{ + CheckForMisbehaviourResult, Height, StatusResult, TimestampAtHeightResult, + VerifyClientMessageMsg, }, - ); - let header = serde_json::from_slice(&verify_client_message_msg.client_message) - .map_err(ContractError::DeserializeClientStateFailed)?; - let bls_verifier = BlsVerifier { deps }; - - ethereum_light_client::verify::verify_header( - ð_consensus_state, - ð_client_state, - env.block.time.seconds(), - &header, - bls_verifier, - ) - .map_err(ContractError::VerifyClientMessageFailed)?; - - Ok(to_json_binary(&Ok::<(), ()>(()))?) -} + }; -pub fn check_for_misbehaviour() -> Result { - Ok(to_json_binary(&CheckForMisbehaviourResult { - found_misbehaviour: false, - })?) -} + use super::{ + get_eth_client_state, get_eth_consensus_state, to_json_binary, Binary, ContractError, Deps, + Env, EthereumCustomQuery, + }; -pub fn timestamp_at_height(env: Env) -> Result { - let now = env.block.time.seconds(); - Ok(to_json_binary(&TimestampAtHeightResult { timestamp: now })?) -} + #[allow(clippy::needless_pass_by_value)] + pub fn verify_client_message( + deps: Deps, + env: Env, + verify_client_message_msg: VerifyClientMessageMsg, + ) -> Result { + let eth_client_state = get_eth_client_state(deps.storage); + let eth_consensus_state = get_eth_consensus_state( + deps.storage, + &Height { + revision_number: 0, + revision_height: eth_client_state.latest_slot, + }, + ); + let header = serde_json::from_slice(&verify_client_message_msg.client_message) + .map_err(ContractError::DeserializeClientStateFailed)?; + let bls_verifier = BlsVerifier { deps }; + + ethereum_light_client::verify::verify_header( + ð_consensus_state, + ð_client_state, + env.block.time.seconds(), + &header, + bls_verifier, + ) + .map_err(ContractError::VerifyClientMessageFailed)?; + + Ok(to_json_binary(&Ok::<(), ()>(()))?) + } + + pub fn check_for_misbehaviour() -> Result { + Ok(to_json_binary(&CheckForMisbehaviourResult { + found_misbehaviour: false, + })?) + } + + #[allow(clippy::needless_pass_by_value)] + pub fn timestamp_at_height(env: Env) -> Result { + let now = env.block.time.seconds(); + Ok(to_json_binary(&TimestampAtHeightResult { timestamp: now })?) + } -pub fn status() -> Result { - Ok(to_json_binary(&StatusResult { - status: "Active".to_string(), - })?) + pub fn status() -> Result { + Ok(to_json_binary(&StatusResult { + status: "Active".to_string(), + })?) + } } #[cfg(test)] @@ -235,7 +276,7 @@ mod tests { use crate::custom_query::EthereumCustomQuery; mod instantiate_tests { - use alloy_primitives::{aliases::B32, FixedBytes, B256, U256}; + use alloy_primitives::{aliases::B32, Address, FixedBytes, B256, U256}; use cosmwasm_std::{ coins, testing::{message_info, mock_env}, @@ -296,7 +337,7 @@ mod tests { epochs_per_sync_committee_period: 0, latest_slot: 42, ibc_commitment_slot: U256::from(0), - ibc_contract_address: Default::default(), + ibc_contract_address: Address::default(), frozen_height: ethereum_light_client::types::height::Height::default(), }; let client_state_bz: Vec = serde_json::to_vec(&client_state).unwrap(); @@ -314,7 +355,7 @@ mod tests { let msg = InstantiateMsg { client_state: client_state_bz.into(), consensus_state: consensus_state_bz.into(), - checksum: "also does not matter yet".as_bytes().into(), + checksum: b"also does not matter yet".into(), }; let res = instantiate(deps.as_mut(), mock_env(), info, msg.clone()).unwrap(); @@ -397,7 +438,7 @@ mod tests { let msg = crate::msg::InstantiateMsg { client_state: Binary::from(client_state_bz), consensus_state: Binary::from(consensus_state_bz), - checksum: "checksum".as_bytes().into(), // TODO: Real checksum important? + checksum: b"checksum".into(), // TODO: Real checksum important? }; instantiate(deps.as_mut(), mock_env(), info, msg).unwrap(); @@ -474,7 +515,7 @@ mod tests { let msg = crate::msg::InstantiateMsg { client_state: Binary::from(client_state_bz), consensus_state: Binary::from(consensus_state_bz), - checksum: "checksum".as_bytes().into(), // TODO: Real checksum important? + checksum: b"checksum".into(), // TODO: Real checksum important? }; instantiate(deps.as_mut(), mock_env(), info, msg).unwrap(); diff --git a/programs/cw-ics08-wasm-eth/src/custom_query.rs b/programs/cw-ics08-wasm-eth/src/custom_query.rs index 218ea1ec..d094856a 100644 --- a/programs/cw-ics08-wasm-eth/src/custom_query.rs +++ b/programs/cw-ics08-wasm-eth/src/custom_query.rs @@ -1,37 +1,56 @@ +//! This module contains the custom `CosmWasm` query for the Ethereum light client + use alloy_primitives::B256; use cosmwasm_std::{Binary, CustomQuery, Deps, QueryRequest}; use ethereum_light_client::types::bls::{BlsPublicKey, BlsSignature, BlsVerify}; use ethereum_utils::{ensure, hex::to_hex}; use thiserror::Error; +/// The custom query for the Ethereum light client +/// This is used to verify BLS signatures in `CosmosSDK` #[derive(serde::Serialize, serde::Deserialize, Clone)] #[serde(rename_all = "snake_case")] +#[allow(clippy::module_name_repetitions)] pub enum EthereumCustomQuery { + /// Verify a BLS signature AggregateVerify { + /// The public keys to verify the signature public_keys: Vec, + /// The message to verify message: Binary, + /// The signature to verify signature: Binary, }, + /// Aggregate public keys Aggregate { + /// The public keys to aggregate public_keys: Vec, }, } impl CustomQuery for EthereumCustomQuery {} +/// The BLS verifier via [`EthereumCustomQuery`] pub struct BlsVerifier<'a> { + /// The `CosmWasm` deps used to query the custom query pub deps: Deps<'a, EthereumCustomQuery>, } -#[derive(Debug, PartialEq, thiserror::Error, Clone)] +/// The error type for invalid signatures +#[derive(Debug, PartialEq, Eq, thiserror::Error, Clone)] #[error("signature cannot be verified (public_keys: {public_keys:?}, msg: {msg}, signature: {signature})", msg = to_hex(.msg))] pub struct InvalidSignatureErr { + /// The public keys used to verify the signature pub public_keys: Vec, + /// The message that was signed pub msg: B256, + /// The signature that was verified pub signature: BlsSignature, } +/// The error type for the BLS verifier #[derive(Error, Debug)] +#[allow(missing_docs)] pub enum BlsVerifierError { #[error("fast aggregate verify error: {0}")] FastAggregateVerify(String), diff --git a/programs/cw-ics08-wasm-eth/src/error.rs b/programs/cw-ics08-wasm-eth/src/error.rs index 0f7715b6..c23247ed 100644 --- a/programs/cw-ics08-wasm-eth/src/error.rs +++ b/programs/cw-ics08-wasm-eth/src/error.rs @@ -1,8 +1,11 @@ +//! Defines the [`ContractError`] type. + use cosmwasm_std::StdError; use ethereum_light_client::error::EthereumIBCError; use thiserror::Error; #[derive(Error, Debug)] +#[allow(missing_docs, clippy::module_name_repetitions)] pub enum ContractError { #[error("{0}")] Std(#[from] StdError), @@ -24,4 +27,10 @@ pub enum ContractError { #[error("Verify client message failed: {0}")] VerifyClientMessageFailed(#[source] EthereumIBCError), + + #[error("prost encoding error: {0}")] + ProstEncodeError(#[from] prost::EncodeError), + + #[error("prost decoding error: {0}")] + ProstDecodeError(#[from] prost::DecodeError), } diff --git a/programs/cw-ics08-wasm-eth/src/lib.rs b/programs/cw-ics08-wasm-eth/src/lib.rs index b6004c71..2a1714eb 100644 --- a/programs/cw-ics08-wasm-eth/src/lib.rs +++ b/programs/cw-ics08-wasm-eth/src/lib.rs @@ -1,8 +1,14 @@ +#![doc = include_str!("../README.md")] +#![deny(clippy::nursery, clippy::pedantic, warnings, missing_docs)] + pub mod contract; pub mod custom_query; -pub mod error; +mod error; +#[allow(clippy::module_name_repetitions)] pub mod msg; pub mod state; +pub use error::ContractError; + #[cfg(test)] mod test; diff --git a/programs/cw-ics08-wasm-eth/src/msg.rs b/programs/cw-ics08-wasm-eth/src/msg.rs index 4e68e810..ac4009f4 100644 --- a/programs/cw-ics08-wasm-eth/src/msg.rs +++ b/programs/cw-ics08-wasm-eth/src/msg.rs @@ -1,135 +1,193 @@ +//! The messages that are passed between the contract and the ibc-go module + use cosmwasm_schema::{cw_serde, QueryResponses}; use cosmwasm_std::Binary; +/// The message to instantiate the contract #[cw_serde] pub struct InstantiateMsg { + /// The client state pub client_state: Binary, + /// The consensus state pub consensus_state: Binary, + /// The checksum of this wasm code pub checksum: Binary, } +/// The unused message to execute the contract #[cw_serde] pub enum ExecuteMsg {} +/// The sudo messages called by `ibc-go` #[cw_serde] pub enum SudoMsg { + /// The message to verify membership VerifyMembership(VerifyMembershipMsg), - + /// The message to verify non-membership VerifyNonMembership(VerifyNonMembershipMsg), - UpdateState(UpdateStateMsg), + /// The message to update the client state + UpdateState(UpdateStateMsg), + /// The message to update the client state on misbehaviour UpdateStateOnMisbehaviour(UpdateStateOnMisbehaviourMsg), - + /// The message to verify the upgrade and update the state VerifyUpgradeAndUpdateState(VerifyUpgradeAndUpdateStateMsg), - + /// The message to migrate the client store MigrateClientStore(MigrateClientStoreMsg), } +/// Verify membership message #[cw_serde] pub struct VerifyMembershipMsg { + /// The proof height pub height: Height, + /// The delay time period (unused) pub delay_time_period: u64, + /// The delay block period (unused) pub delay_block_period: u64, + /// The proof bytes pub proof: Binary, + /// The path to the value pub merkle_path: MerklePath, + /// The value to verify pub value: Binary, } +/// Verify non-membership message #[cw_serde] pub struct VerifyNonMembershipMsg { + /// The proof height pub height: Height, + /// The delay time period (unused) pub delay_time_period: u64, + /// The delay block period (unused) pub delay_block_period: u64, + /// The proof bytes pub proof: Binary, + /// The path to the empty value pub merkle_path: MerklePath, } +/// Update state message #[cw_serde] pub struct UpdateStateMsg { + /// The client message pub client_message: Binary, } +/// Update state on misbehaviour message #[cw_serde] pub struct UpdateStateOnMisbehaviourMsg { + /// The client message pub client_message: Binary, } +/// Verify upgrade and update state message #[cw_serde] pub struct VerifyUpgradeAndUpdateStateMsg { + /// The upgraded client state pub upgrade_client_state: Binary, + /// The upgraded consensus state pub upgrade_consensus_state: Binary, + /// The proof of the upgraded client state pub proof_upgrade_client: Binary, + /// The proof of the upgraded consensus state pub proof_upgrade_consensus_state: Binary, } +/// Migrate client store message #[cw_serde] pub struct MigrateClientStoreMsg {} +/// The query messages called by `ibc-go` #[cw_serde] #[derive(QueryResponses)] pub enum QueryMsg { + /// The message to verify the client message #[returns[()]] VerifyClientMessage(VerifyClientMessageMsg), + /// The message to check for misbehaviour #[returns[CheckForMisbehaviourResult]] CheckForMisbehaviour(CheckForMisbehaviourMsg), + /// The message to get the timestamp at height #[returns[TimestampAtHeightResult]] TimestampAtHeight(TimestampAtHeightMsg), + /// The message to get the status #[returns[StatusResult]] Status(StatusMsg), } +/// The message to verify the client message #[cw_serde] pub struct VerifyClientMessageMsg { + /// The client message to verify pub client_message: Binary, } +/// The message to check for misbehaviour #[cw_serde] pub struct CheckForMisbehaviourMsg { + /// The client message to check pub client_message: Binary, } +/// The message to get the timestamp at height #[cw_serde] pub struct TimestampAtHeightMsg { + /// The height to get the timestamp at pub height: Height, } +/// The status query message #[cw_serde] pub struct StatusMsg {} +/// Height of the ethereum chain #[cw_serde] pub struct Height { - /// the revision that the client is currently on + /// The revision that the client is currently on + /// Always zero in the ethereum light client #[serde(default)] pub revision_number: u64, - /// **revision_height** is a height of remote chain + /// The execution height of ethereum chain #[serde(default)] pub revision_height: u64, } +/// The result of updating the client state #[cw_serde] pub struct UpdateStateResult { + /// The updated client state heights pub heights: Vec, } +/// The merkle path #[cw_serde] pub struct MerklePath { + /// The key path pub key_path: Vec, } +/// The response to the status query #[cw_serde] pub struct StatusResult { + /// The status of the client pub status: String, } +/// The response to the check for misbehaviour query #[cw_serde] pub struct CheckForMisbehaviourResult { + /// Whether the client has found misbehaviour pub found_misbehaviour: bool, } +/// The response to the timestamp at height query #[cw_serde] pub struct TimestampAtHeightResult { + /// The timestamp at the height (in nanoseconds) pub timestamp: u64, } diff --git a/programs/cw-ics08-wasm-eth/src/state.rs b/programs/cw-ics08-wasm-eth/src/state.rs index a924ada5..89519c34 100644 --- a/programs/cw-ics08-wasm-eth/src/state.rs +++ b/programs/cw-ics08-wasm-eth/src/state.rs @@ -1,4 +1,6 @@ -use cosmwasm_std::Deps; +//! State management for the Ethereum light client + +use cosmwasm_std::Storage; use ethereum_light_client::client_state::ClientState as EthClientState; use ethereum_light_client::consensus_state::ConsensusState as EthConsensusState; use ibc_proto::{ @@ -9,12 +11,15 @@ use ibc_proto::{ }; use prost::Message; -use crate::{custom_query::EthereumCustomQuery, msg::Height}; +use crate::msg::Height; -// Client state that is stored by the host +/// The store key used by `ibc-go` to store the client state pub const HOST_CLIENT_STATE_KEY: &str = "clientState"; +/// The store key used by `ibc-go` to store the consensus states pub const HOST_CONSENSUS_STATES_KEY: &str = "consensusStates"; +/// The key used to store the consensus states by height +#[must_use] pub fn consensus_db_key(height: &Height) -> String { format!( "{}/{}-{}", @@ -23,8 +28,12 @@ pub fn consensus_db_key(height: &Height) -> String { } // TODO: Proper errors -pub fn get_eth_client_state(deps: Deps) -> EthClientState { - let wasm_client_state_any_bz = deps.storage.get(HOST_CLIENT_STATE_KEY.as_bytes()).unwrap(); +/// Get the Ethereum client state +/// # Panics +/// Panics if the client state is not found or cannot be deserialized +#[allow(clippy::module_name_repetitions)] +pub fn get_eth_client_state(storage: &dyn Storage) -> EthClientState { + let wasm_client_state_any_bz = storage.get(HOST_CLIENT_STATE_KEY.as_bytes()).unwrap(); let wasm_client_state_any = Any::decode(wasm_client_state_any_bz.as_slice()).unwrap(); let wasm_client_state = WasmClientState::decode(wasm_client_state_any.value.as_slice()).unwrap(); @@ -34,14 +43,12 @@ pub fn get_eth_client_state(deps: Deps) -> EthClientState { } // TODO: Proper errors -pub fn get_eth_consensus_state( - deps: Deps, - height: &Height, -) -> EthConsensusState { - let wasm_consensus_state_any_bz = deps - .storage - .get(consensus_db_key(height).as_bytes()) - .unwrap(); +/// Get the Ethereum consensus state at a given height +/// # Panics +/// Panics if the consensus state is not found or cannot be deserialized +#[allow(clippy::module_name_repetitions)] +pub fn get_eth_consensus_state(storage: &dyn Storage, height: &Height) -> EthConsensusState { + let wasm_consensus_state_any_bz = storage.get(consensus_db_key(height).as_bytes()).unwrap(); let wasm_consensus_state_any = Any::decode(wasm_consensus_state_any_bz.as_slice()).unwrap(); let wasm_consensus_state = WasmConsensusState::decode(wasm_consensus_state_any.value.as_slice()).unwrap();