From 4417168d99b28b194032eb0437bf09f5b2751ce9 Mon Sep 17 00:00:00 2001 From: aeryz Date: Wed, 30 Aug 2023 19:14:53 +0300 Subject: [PATCH] feat(cometbls-lc): use `ics008-wasm-client` Signed-off-by: aeryz --- lib/ics-008-wasm-client/src/ibc_client.rs | 10 +- .../cometbls-light-client/src/bin/schema.rs | 1 - .../cometbls-light-client/src/client.rs | 303 ++++++++++++++++++ .../cometbls-light-client/src/contract.rs | 248 +------------- .../cometbls-light-client/src/errors.rs | 20 +- .../cometbls-light-client/src/lib.rs | 4 +- .../cometbls-light-client/src/msg.rs | 5 - .../cometbls-light-client/src/state.rs | 121 ------- .../cometbls-light-client/src/types.rs | 1 - .../ethereum-light-client/src/client.rs | 13 +- .../ethereum-light-client/src/errors.rs | 4 +- 11 files changed, 345 insertions(+), 385 deletions(-) delete mode 100644 light-clients/cometbls-light-client/src/bin/schema.rs create mode 100644 light-clients/cometbls-light-client/src/client.rs delete mode 100644 light-clients/cometbls-light-client/src/msg.rs delete mode 100644 light-clients/cometbls-light-client/src/state.rs delete mode 100644 light-clients/cometbls-light-client/src/types.rs diff --git a/lib/ics-008-wasm-client/src/ibc_client.rs b/lib/ics-008-wasm-client/src/ibc_client.rs index aa46db24c3..8f91687699 100644 --- a/lib/ics-008-wasm-client/src/ibc_client.rs +++ b/lib/ics-008-wasm-client/src/ibc_client.rs @@ -25,7 +25,7 @@ pub trait IBCClient { fn execute( deps: DepsMut, - _env: Env, + env: Env, _info: MessageInfo, msg: ExecuteMsg, ) -> Result { @@ -70,13 +70,13 @@ pub trait IBCClient { } => { if let Some(header) = header { let header = Self::Header::try_from_proto_bytes(&header.data)?; - Self::verify_header(deps.as_ref(), header) + Self::verify_header(deps.as_ref(), env, header) } else if let Some(misbehaviour) = misbehaviour { let misbehaviour = Self::Misbehaviour::try_from_proto_bytes(&misbehaviour.data)?; Self::verify_misbehaviour(deps.as_ref(), misbehaviour) } else { - // Note(aeryz): There is nothing in spec that makes either of the fields to present + // Note(aeryz): Host implementation doesn't count this as error Ok(ContractResult::valid(None)) } } @@ -85,7 +85,7 @@ pub trait IBCClient { } => { if let Some(header) = header { let header = Self::Header::try_from_proto_bytes(&header.data)?; - Self::update_state(deps, header) + Self::update_state(deps, env, header) } else { Err(Error::NotSpecCompilant( "`UpdateState` is not valid for misbehaviour".to_string(), @@ -121,6 +121,7 @@ pub trait IBCClient { fn verify_header( deps: Deps, + env: Env, header: Self::Header, ) -> Result; @@ -131,6 +132,7 @@ pub trait IBCClient { fn update_state( deps: DepsMut, + env: Env, header: Self::Header, ) -> Result; diff --git a/light-clients/cometbls-light-client/src/bin/schema.rs b/light-clients/cometbls-light-client/src/bin/schema.rs deleted file mode 100644 index f328e4d9d0..0000000000 --- a/light-clients/cometbls-light-client/src/bin/schema.rs +++ /dev/null @@ -1 +0,0 @@ -fn main() {} diff --git a/light-clients/cometbls-light-client/src/client.rs b/light-clients/cometbls-light-client/src/client.rs new file mode 100644 index 0000000000..a7a8846bcf --- /dev/null +++ b/light-clients/cometbls-light-client/src/client.rs @@ -0,0 +1,303 @@ +use cosmwasm_std::{Binary, Deps, DepsMut, Empty, Env}; +use ics008_wasm_client::{ + storage_utils::{ + read_client_state, read_consensus_state, save_client_state, save_consensus_state, + }, + ContractResult, IBCClient, MerklePath, Status, StorageState, +}; +use prost::Message; +use unionlabs::{ + ibc::{ + core::{client::height::Height, commitment::merkle_root::MerkleRoot}, + google::protobuf::timestamp::Timestamp, + lightclients::cometbls::{ + client_state::ClientState, consensus_state::ConsensusState, header::Header, + }, + }, + tendermint::types::commit::Commit, +}; + +use crate::{errors::Error, zkp_verifier::verify_zkp}; + +type WasmClientState = unionlabs::ibc::lightclients::wasm::client_state::ClientState; +type WasmConsensusState = + unionlabs::ibc::lightclients::wasm::consensus_state::ConsensusState; + +pub struct CometblsLightClient; + +impl IBCClient for CometblsLightClient { + type Error = Error; + + type CustomQuery = Empty; + + type Header = Header; + + // TODO(aeryz): Change this to appropriate misbehavior type when it is implemented + type Misbehaviour = Header; + + type ClientState = ClientState; + + type ConsensusState = ConsensusState; + + fn verify_membership( + _deps: Deps, + _height: Height, + _delay_time_period: u64, + _delay_block_period: u64, + _proof: Binary, + _path: MerklePath, + _value: StorageState, + ) -> Result { + Ok(ContractResult::valid(None)) + } + + fn verify_header( + deps: Deps, + env: Env, + header: Self::Header, + ) -> Result { + let client_state: WasmClientState = read_client_state(deps)?; + let consensus_state: WasmConsensusState = + read_consensus_state(deps, &header.trusted_height)?.ok_or( + Error::ConsensusStateNotFound( + header.trusted_height.revision_number, + header.trusted_height.revision_height, + ), + )?; + + let untrusted_height_number = header.signed_header.commit.height.inner() as u64; + let trusted_height_number = header.trusted_height.revision_number; + + if untrusted_height_number <= trusted_height_number { + return Err(Error::InvalidHeader( + "header height <= consensus state height".into(), + )); + } + + let trusted_timestamp = consensus_state.timestamp; + let untrusted_timestamp = header.signed_header.header.time.seconds; + + if untrusted_timestamp.inner() as u64 <= trusted_timestamp { + return Err(Error::InvalidHeader( + "header time <= consensus state time".into(), + )); + } + + let current_time: Timestamp = env + .block + .time + .try_into() + .map_err(|_| Error::InvalidHeader("timestamp conversion failed".into()))?; + + if current_time + .duration_since(&header.signed_header.header.time) + .ok_or(Error::DurationAdditionOverflow)? + > client_state.data.trusting_period + { + return Err(Error::InvalidHeader("header expired".into())); + } + + let max_clock_drift = + current_time.seconds.inner() + client_state.data.max_clock_drift.seconds().inner(); + + if untrusted_timestamp.inner() >= max_clock_drift { + return Err(Error::InvalidHeader("header back to the future".into())); + } + + let trusted_validators_hash = consensus_state.data.next_validators_hash; + + let untrusted_validators_hash = if untrusted_height_number == trusted_height_number + 1 { + trusted_validators_hash.clone() + } else { + header.untrusted_validator_set_root + }; + + let expected_block_hash = header + .signed_header + .header + .calculate_merkle_root() + .ok_or(Error::UnableToCalculateMerkleRoot)?; + + if header.signed_header.commit.block_id.hash.0.as_slice() != expected_block_hash { + return Err(Error::InvalidHeader( + "commit.block_id.hash != header.root()".into(), + )); + } + + let signed_vote = canonical_vote( + &header.signed_header.commit, + header.signed_header.header.chain_id.clone(), + expected_block_hash, + ) + .encode_length_delimited_to_vec(); + + if !verify_zkp( + &trusted_validators_hash.0, + &untrusted_validators_hash.0, + &signed_vote, + &header.zero_knowledge_proof, + ) { + return Err(Error::InvalidZKP); + } + + Ok(ContractResult::valid(None)) + } + + fn verify_misbehaviour( + _deps: Deps, + _misbehaviour: Self::Misbehaviour, + ) -> Result { + Ok(ContractResult::valid(None)) + } + + fn update_state( + mut deps: DepsMut, + _env: Env, + header: Self::Header, + ) -> Result { + let mut client_state: WasmClientState = read_client_state(deps.as_ref())?; + let mut consensus_state: WasmConsensusState = + read_consensus_state(deps.as_ref(), &header.trusted_height)?.ok_or( + Error::ConsensusStateNotFound( + header.trusted_height.revision_number, + header.trusted_height.revision_height, + ), + )?; + + let untrusted_height = Height::new( + header.trusted_height.revision_number, + header.signed_header.commit.height.inner() as u64, + ); + + if untrusted_height > client_state.latest_height { + client_state.latest_height = untrusted_height; + } + + consensus_state.data.root = MerkleRoot { + hash: header.signed_header.header.app_hash, + }; + + let untrusted_height_number = header.signed_header.commit.height.inner() as u64; + let trusted_height_number = header.trusted_height.revision_number; + + let untrusted_validators_hash = if untrusted_height_number == trusted_height_number + 1 { + consensus_state.data.next_validators_hash.clone() + } else { + header.untrusted_validator_set_root + }; + + consensus_state.data.next_validators_hash = untrusted_validators_hash; + consensus_state.timestamp = header.signed_header.header.time.seconds.inner() as u64; + + save_client_state(deps.branch(), client_state); + save_consensus_state(deps, consensus_state, &untrusted_height); + + Ok(ContractResult::valid(None)) + } + + fn update_state_on_misbeviour( + _deps: Deps, + _client_message: ics008_wasm_client::ClientMessage, + ) -> Result { + Ok(ContractResult::valid(None)) + } + + fn check_for_misbehaviour( + _deps: Deps, + _client_message: ics008_wasm_client::ClientMessage, + ) -> Result { + Ok(ContractResult::valid(None)) + } + + fn verify_upgrade_and_update_state( + _deps: Deps, + _upgrade_client_state: Self::ClientState, + _upgrade_consensus_state: Self::ConsensusState, + _proof_upgrade_client: Binary, + _proof_upgrade_consensus_state: Binary, + ) -> Result { + Ok(ContractResult::valid(None)) + } + + fn check_substitute_and_update_state( + _deps: Deps, + ) -> Result { + Ok(ContractResult::valid(None)) + } + + fn status( + deps: Deps, + env: &cosmwasm_std::Env, + ) -> Result { + let client_state: WasmClientState = read_client_state(deps)?; + + // TODO(aeryz): make client state optional + if client_state.data.frozen_height.revision_height == 0 { + return Ok(Status::Frozen.into()); + } + + let Some(consensus_state) = read_consensus_state::( + deps, + &client_state.latest_height, + )? + else { + return Ok(Status::Expired.into()); + }; + + if is_client_expired( + consensus_state.timestamp, + client_state + .data + .trusting_period + .seconds() + .inner() + // NOTE: trusting_period *should* be strictly positive; enforce this somehow? + .try_into() + .unwrap_or_default(), + env.block.time.seconds(), + ) { + return Ok(Status::Expired.into()); + } + + Ok(Status::Active.into()) + } + + fn export_metadata( + _deps: Deps, + _env: &cosmwasm_std::Env, + ) -> Result { + Ok(ics008_wasm_client::QueryResponse { + status: String::new(), + genesis_metadata: vec![], + }) + } +} + +fn is_client_expired( + consensus_state_timestamp: u64, + trusting_period: u64, + current_block_time: u64, +) -> bool { + consensus_state_timestamp + trusting_period < current_block_time +} + +fn canonical_vote( + commit: &Commit, + chain_id: String, + expected_block_hash: [u8; 32], +) -> protos::tendermint::types::CanonicalVote { + protos::tendermint::types::CanonicalVote { + r#type: protos::tendermint::types::SignedMsgType::Precommit as i32, + height: commit.height.inner(), + round: commit.round.inner() as i64, + // TODO(aeryz): Implement BlockId to proto::CanonicalBlockId + block_id: Some(protos::tendermint::types::CanonicalBlockId { + hash: expected_block_hash.to_vec(), + part_set_header: Some(protos::tendermint::types::CanonicalPartSetHeader { + total: commit.block_id.part_set_header.total, + hash: commit.block_id.part_set_header.hash.0.to_vec(), + }), + }), + chain_id, + } +} diff --git a/light-clients/cometbls-light-client/src/contract.rs b/light-clients/cometbls-light-client/src/contract.rs index 32b5d74cd9..9c1e0be636 100644 --- a/light-clients/cometbls-light-client/src/contract.rs +++ b/light-clients/cometbls-light-client/src/contract.rs @@ -1,30 +1,11 @@ use cosmwasm_std::{ - entry_point, to_binary, Binary, Deps, DepsMut, Env, MessageInfo, QueryResponse, Response, - StdError, -}; -use prost::Message; -use protos::tendermint::types::{CanonicalBlockId, CanonicalPartSetHeader, SignedMsgType}; -use unionlabs::{ - ibc::{ - core::{client::height::Height, commitment::merkle_root::MerkleRoot}, - google::protobuf::timestamp::Timestamp, - lightclients::cometbls::header::Header, - }, - tendermint::types::commit::Commit, - TryFromProto, -}; -use wasm_light_client_types::msg::{ - ClientMessage, ContractResult, MerklePath, Status, StatusResponse, + entry_point, to_binary, Deps, DepsMut, Env, MessageInfo, QueryResponse, Response, }; +use ics008_wasm_client::{ExecuteMsg, IBCClient, QueryMsg}; -use crate::{ - errors::Error, - msg::{ExecuteMsg, InstantiateMsg, QueryMsg}, - state::{ - read_client_state, read_consensus_state, save_consensus_state, save_wasm_client_state, - }, - zkp_verifier::verify_zkp, -}; +use crate::{client::CometblsLightClient, errors::Error}; + +pub struct InstantiateMsg {} #[entry_point] pub fn instantiate( @@ -40,230 +21,17 @@ pub fn instantiate( pub fn execute( deps: DepsMut, env: Env, - _info: MessageInfo, + info: MessageInfo, msg: ExecuteMsg, ) -> Result { - let result = match msg { - ExecuteMsg::VerifyMembership { - height, - delay_time_period, - delay_block_period, - proof, - path, - value, - } => verify_membership( - deps.as_ref(), - height, - delay_time_period, - delay_block_period, - proof, - path, - value, - ), - ExecuteMsg::UpdateState { - client_message: ClientMessage { header, .. }, - } => { - if let Some(header) = header { - let header = Header::try_from_proto_bytes(&header.data).map_err(|err| { - Error::decode(format!( - "when converting proto header to header in update: {err:#?}" - )) - })?; - update_header(deps, env, header) - } else { - Err(StdError::not_found("Not implemented").into()) - } - } - _ => Ok(ContractResult::valid(None)), - }?; + let result = CometblsLightClient::execute(deps, env, info, msg)?; Ok(Response::default().set_data(result.encode()?)) } -/// Verifies if the `value` is committed at `path` in the counterparty light client. -pub fn verify_membership( - _deps: Deps, - _height: Height, - _delay_time_period: u64, - _delay_block_period: u64, - _proof: Binary, - _path: MerklePath, - _value: Binary, -) -> Result { - // TODO: #514 - Ok(ContractResult::valid(None)) -} - -pub fn update_header(mut deps: DepsMut, env: Env, header: Header) -> Result { - let mut client_state = read_client_state(deps.as_ref())?; - let mut consensus_state = read_consensus_state(deps.as_ref(), &header.trusted_height)?.ok_or( - Error::ConsensusStateNotFound( - header.trusted_height.revision_number, - header.trusted_height.revision_height, - ), - )?; - - let untrusted_height_number = header.signed_header.commit.height.inner() as u64; - let trusted_height_number = header.trusted_height.revision_number; - - if untrusted_height_number <= trusted_height_number { - return Err(Error::InvalidHeader( - "header height <= consensus state height".into(), - )); - } - - let trusted_timestamp = consensus_state.timestamp; - let untrusted_timestamp = header.signed_header.header.time.seconds; - - if untrusted_timestamp.inner() as u64 <= trusted_timestamp { - return Err(Error::InvalidHeader( - "header time <= consensus state time".into(), - )); - } - - let current_time: Timestamp = env - .block - .time - .try_into() - .map_err(|_| Error::InvalidHeader("timestamp conversion failed".into()))?; - - if current_time - .duration_since(&header.signed_header.header.time) - .ok_or(Error::DurationAdditionOverflow)? - > client_state.data.trusting_period - { - return Err(Error::InvalidHeader("header expired".into())); - } - - let max_clock_drift = - current_time.seconds.inner() + client_state.data.max_clock_drift.seconds().inner(); - - if untrusted_timestamp.inner() >= max_clock_drift { - return Err(Error::InvalidHeader("header back to the future".into())); - } - - let trusted_validators_hash = consensus_state.data.next_validators_hash.clone(); - - let untrusted_validators_hash = if untrusted_height_number == trusted_height_number + 1 { - trusted_validators_hash.clone() - } else { - header.untrusted_validator_set_root - }; - - let expected_block_hash = header - .signed_header - .header - .calculate_merkle_root() - .ok_or(Error::UnableToCalculateMerkleRoot)?; - - if header.signed_header.commit.block_id.hash.0.as_slice() != expected_block_hash { - return Err(Error::InvalidHeader( - "commit.block_id.hash != header.root()".into(), - )); - } - - let signed_vote = canonical_vote( - &header.signed_header.commit, - header.signed_header.header.chain_id.clone(), - expected_block_hash, - ) - .encode_length_delimited_to_vec(); - - if !verify_zkp( - &trusted_validators_hash.0, - &untrusted_validators_hash.0, - &signed_vote, - &header.zero_knowledge_proof, - ) { - return Err(Error::InvalidZKP); - } - - let untrusted_height = Height::new( - header.trusted_height.revision_number, - header.signed_header.commit.height.inner() as u64, - ); - - if untrusted_height > client_state.latest_height { - client_state.latest_height = untrusted_height; - } - - consensus_state.data.root = MerkleRoot { - hash: header.signed_header.header.app_hash, - }; - - consensus_state.data.next_validators_hash = untrusted_validators_hash; - consensus_state.timestamp = header.signed_header.header.time.seconds.inner() as u64; - - save_wasm_client_state(deps.branch(), client_state); - save_consensus_state(deps, consensus_state, untrusted_height)?; - - Ok(ContractResult::valid(None)) -} - -fn canonical_vote( - commit: &Commit, - chain_id: String, - expected_block_hash: [u8; 32], -) -> protos::tendermint::types::CanonicalVote { - protos::tendermint::types::CanonicalVote { - r#type: SignedMsgType::Precommit as i32, - height: commit.height.inner(), - round: commit.round.inner() as i64, - // TODO(aeryz): Implement BlockId to proto::CanonicalBlockId - block_id: Some(CanonicalBlockId { - hash: expected_block_hash.to_vec(), - part_set_header: Some(CanonicalPartSetHeader { - total: commit.block_id.part_set_header.total, - hash: commit.block_id.part_set_header.hash.0.to_vec(), - }), - }), - chain_id, - } -} - #[entry_point] pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> Result { - let response = match msg { - QueryMsg::Status {} => query_status(deps, &env)?, - }; + let response = CometblsLightClient::query(deps, env, msg)?; to_binary(&response).map_err(Into::into) } - -fn query_status(deps: Deps, env: &Env) -> Result { - let client_state = read_client_state(deps)?; - - // TODO(aeryz): make client state optional - if client_state.data.frozen_height.revision_height == 0 { - return Ok(Status::Frozen.into()); - } - - let Some(consensus_state) = read_consensus_state(deps, &client_state.latest_height)? else { - return Ok(Status::Expired.into()); - }; - - if is_client_expired( - consensus_state.timestamp, - client_state - .data - .trusting_period - .seconds() - .inner() - // NOTE: trusting_period *should* be strictly positive; enforce this somehow? - .try_into() - .unwrap_or_default(), - env.block.time.seconds(), - ) { - return Ok(Status::Expired.into()); - } - - Ok(Status::Active.into()) -} - -fn is_client_expired( - consensus_state_timestamp: u64, - trusting_period: u64, - current_block_time: u64, -) -> bool { - consensus_state_timestamp + trusting_period < current_block_time -} diff --git a/light-clients/cometbls-light-client/src/errors.rs b/light-clients/cometbls-light-client/src/errors.rs index 95498ff45b..068669f488 100644 --- a/light-clients/cometbls-light-client/src/errors.rs +++ b/light-clients/cometbls-light-client/src/errors.rs @@ -1,5 +1,8 @@ use cosmwasm_std::StdError; use thiserror::Error as ThisError; +use unionlabs::{ + ibc::lightclients::cometbls::header::Header, TryFromProtoBytesError, TryFromProtoErrorOf, +}; #[derive(ThisError, Debug, PartialEq)] pub enum Error { @@ -96,6 +99,9 @@ pub enum Error { #[error("Custom query: {0}")] CustomQuery(String), + + #[error("Wasm client error: {0}")] + Wasm(String), } impl Error { @@ -123,10 +129,18 @@ impl Error { } } -impl From for Error { - fn from(error: wasm_light_client_types::Error) -> Self { +impl From>> for Error { + fn from(value: TryFromProtoBytesError>) -> Self { + Self::DecodeError(format!("{:?}", value)) + } +} + +impl From for Error { + fn from(error: ics008_wasm_client::Error) -> Self { match error { - wasm_light_client_types::Error::Decode(e) => Error::DecodeError(e), + ics008_wasm_client::Error::Decode(e) => Error::DecodeError(e), + ics008_wasm_client::Error::NotSpecCompilant(e) => Error::Wasm(e), + ics008_wasm_client::Error::ClientStateNotFound => Error::Wasm(format!("{error:#?}")), } } } diff --git a/light-clients/cometbls-light-client/src/lib.rs b/light-clients/cometbls-light-client/src/lib.rs index b3a96d7068..b9eb16eb16 100644 --- a/light-clients/cometbls-light-client/src/lib.rs +++ b/light-clients/cometbls-light-client/src/lib.rs @@ -1,6 +1,4 @@ +pub mod client; pub mod contract; pub mod errors; -pub mod msg; -pub mod state; -pub mod types; pub mod zkp_verifier; diff --git a/light-clients/cometbls-light-client/src/msg.rs b/light-clients/cometbls-light-client/src/msg.rs deleted file mode 100644 index 8d638cf4e8..0000000000 --- a/light-clients/cometbls-light-client/src/msg.rs +++ /dev/null @@ -1,5 +0,0 @@ -use cosmwasm_schema::cw_serde; -pub use wasm_light_client_types::msg::{ExecuteMsg, QueryMsg}; - -#[cw_serde] -pub struct InstantiateMsg {} diff --git a/light-clients/cometbls-light-client/src/state.rs b/light-clients/cometbls-light-client/src/state.rs deleted file mode 100644 index da3da26d8f..0000000000 --- a/light-clients/cometbls-light-client/src/state.rs +++ /dev/null @@ -1,121 +0,0 @@ -use cosmwasm_std::{Deps, DepsMut}; -use unionlabs::{ - ibc::{ - core::client::height::Height, - google::protobuf::any::Any, - lightclients::{cometbls, wasm}, - }, - IntoProto, TryFromProto, -}; - -use crate::errors::Error; - -// Client state that is stored by the host -pub const HOST_CLIENT_STATE_KEY: &str = "clientState"; -pub const HOST_CONSENSUS_STATES_KEY: &str = "consensusStates"; - -fn consensus_db_key(height: &Height) -> String { - format!( - "{}/{}-{}", - HOST_CONSENSUS_STATES_KEY, height.revision_number, height.revision_height - ) -} - -/// Reads the client state from the host. -/// -/// The host stores the client state with 'HOST_CLIENT_STATE_KEY' key in the following format: -/// - type_url: WASM_CLIENT_STATE_TYPE_URL -/// - value: (PROTO_ENCODED_WASM_CLIENT_STATE) -/// - code_id: Code ID of this contract's code -/// - latest_height: Latest height that the state is updated -/// - data: Contract defined raw bytes, which we use as protobuf encoded ethereum client state. -pub fn read_client_state( - deps: Deps, -) -> Result, Error> { - let any_state = deps - .storage - .get(HOST_CLIENT_STATE_KEY.as_bytes()) - .ok_or(Error::ClientStateNotFound)?; - - Any::try_from_proto_bytes(any_state.as_slice()) - .map(|any| any.0) - .map_err(|err| { - Error::decode(format!( - "when decoding raw bytes to any in `read_client_state`: {err:#?}" - )) - }) -} - -/// Reads the consensus state at a specific height from the host. -/// -/// The host stores the consensus state with 'HOST_CONSENSUS_STATES_KEY/REVISION_NUMBER-REVISION_HEIGHT' -/// key in the following format: -/// - type_url: WASM_CONSENSUS_STATE_TYPE_URL -/// - value: (PROTO_ENCODED_WASM_CLIENT_STATE) -/// - timestamp: Time of this consensus state. -/// - data: Contract defined raw bytes, which we use as protobuf encoded ethereum consensus state. -pub fn read_consensus_state( - deps: Deps, - height: &Height, -) -> Result< - Option>, - Error, -> { - deps.storage - .get(consensus_db_key(height).as_bytes()) - .map(|bytes| Any::try_from_proto_bytes(&bytes).map(|any| any.0)) - .transpose() - .map_err(|err| Error::decode(format!("error reading consensus state: {err:#?}"))) -} - -pub fn save_wasm_client_state( - deps: DepsMut, - wasm_client_state: wasm::client_state::ClientState, -) { - let any_state = Any(wasm_client_state); - deps.storage.set( - HOST_CLIENT_STATE_KEY.as_bytes(), - any_state.into_proto_bytes().as_slice(), - ); -} - -/// Update the client state on the host store. -pub fn update_client_state( - deps: DepsMut, - mut wasm_client_state: wasm::client_state::ClientState, - // new_client_state: ethereum::client_state::ClientState, - latest_execution_height: u64, -) { - // wasm_client_state.data = new_client_state; - wasm_client_state.latest_height = Height { - revision_number: 0, - revision_height: latest_execution_height, - }; - - save_wasm_client_state(deps, wasm_client_state); -} - -pub fn save_wasm_consensus_state( - deps: DepsMut, - wasm_consensus_state: wasm::consensus_state::ConsensusState< - cometbls::consensus_state::ConsensusState, - >, - height: &Height, -) { - deps.storage.set( - consensus_db_key(height).as_bytes(), - &Any(wasm_consensus_state).into_proto_bytes(), - ); -} - -/// Save new consensus state at height `consensus_state.slot` to the host store. -pub fn save_consensus_state( - deps: DepsMut, - wasm_consensus_state: wasm::consensus_state::ConsensusState< - cometbls::consensus_state::ConsensusState, - >, - height: Height, -) -> Result<(), Error> { - save_wasm_consensus_state(deps, wasm_consensus_state, &height); - Ok(()) -} diff --git a/light-clients/cometbls-light-client/src/types.rs b/light-clients/cometbls-light-client/src/types.rs deleted file mode 100644 index 8b13789179..0000000000 --- a/light-clients/cometbls-light-client/src/types.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/light-clients/ethereum-light-client/src/client.rs b/light-clients/ethereum-light-client/src/client.rs index 55ab7d5c3d..8b87761b95 100644 --- a/light-clients/ethereum-light-client/src/client.rs +++ b/light-clients/ethereum-light-client/src/client.rs @@ -51,6 +51,7 @@ impl IBCClient for EthereumLightClient { type Header = Header; + // TODO(aeryz): Change this to appropriate misbehavior type when it is implemented type Misbehaviour = Header; type ClientState = ClientState; @@ -114,6 +115,7 @@ impl IBCClient for EthereumLightClient { fn verify_header( deps: Deps, + _env: Env, header: Self::Header, ) -> Result { let trusted_sync_committee = header.trusted_sync_committee; @@ -185,6 +187,7 @@ impl IBCClient for EthereumLightClient { fn update_state( mut deps: DepsMut, + _env: Env, header: Self::Header, ) -> Result { let trusted_sync_committee = header.trusted_sync_committee; @@ -686,8 +689,8 @@ mod test { ]; for update in updates { - EthereumLightClient::verify_header(deps.as_ref(), update.clone()).unwrap(); - EthereumLightClient::update_state(deps.as_mut(), update.clone()).unwrap(); + EthereumLightClient::verify_header(deps.as_ref(), mock_env(), update.clone()).unwrap(); + EthereumLightClient::update_state(deps.as_mut(), mock_env(), update.clone()).unwrap(); // Consensus state is saved to the updated height. if update.consensus_update.attested_header.beacon.slot > update.trusted_sync_committee.trusted_height.revision_height @@ -840,21 +843,21 @@ mod test { .trusted_sync_committee .sync_committee .aggregate_pubkey = pubkey; - assert!(EthereumLightClient::verify_header(deps.as_ref(), update).is_err()); + assert!(EthereumLightClient::verify_header(deps.as_ref(), mock_env(), update).is_err()); } #[test] fn verify_header_fails_when_finalized_header_execution_branch_merkle_is_invalid() { let (deps, mut update) = prepare_for_fail_tests(); update.consensus_update.finalized_header.execution_branch[0].0[0] += 1; - assert!(EthereumLightClient::verify_header(deps.as_ref(), update).is_err()); + assert!(EthereumLightClient::verify_header(deps.as_ref(), mock_env(), update).is_err()); } #[test] fn verify_header_fails_when_finality_branch_merkle_is_invalid() { let (deps, mut update) = prepare_for_fail_tests(); update.consensus_update.finality_branch[0].0[0] += 1; - assert!(EthereumLightClient::verify_header(deps.as_ref(), update).is_err()); + assert!(EthereumLightClient::verify_header(deps.as_ref(), mock_env(), update).is_err()); } #[test] diff --git a/light-clients/ethereum-light-client/src/errors.rs b/light-clients/ethereum-light-client/src/errors.rs index 1d8ba5ffbd..a9b2fd9f5e 100644 --- a/light-clients/ethereum-light-client/src/errors.rs +++ b/light-clients/ethereum-light-client/src/errors.rs @@ -131,9 +131,9 @@ impl From>>> for Error impl From for Error { fn from(error: ics008_wasm_client::Error) -> Self { match error { - ics008_wasm_client::Error::Decode(e) => Error::Wasm(e), + ics008_wasm_client::Error::Decode(e) => Error::DecodeError(e), ics008_wasm_client::Error::NotSpecCompilant(e) => Error::Wasm(e), - ics008_wasm_client::Error::ClientStateNotFound => Error::Wasm(format!("err:#?")), + ics008_wasm_client::Error::ClientStateNotFound => Error::Wasm(format!("{error:#?}")), } } }