From f2f6a181d92cfae2c2c370183800b285b92f0bf0 Mon Sep 17 00:00:00 2001 From: Vladislav Markushin Date: Thu, 20 Jul 2023 15:22:28 -0300 Subject: [PATCH 01/37] Pass ConsensusState and ClientState in contract initialization method --- .../ics07-tendermint-cw/src/client.rs | 52 +++++++++++++----- .../ics07-tendermint-cw/src/context.rs | 51 ++++++++++++++--- .../ics07-tendermint-cw/src/contract.rs | 54 +++++++++++++----- light-clients/ics07-tendermint-cw/src/msg.rs | 3 - light-clients/ics08-wasm/src/client_state.rs | 14 +++++ .../ics08-wasm/src/consensus_state.rs | 6 ++ light-clients/ics08-wasm/src/instantiate.rs | 15 +++++ light-clients/ics08-wasm/src/lib.rs | 1 + light-clients/ics10-grandpa-cw/src/client.rs | 54 +++++++++++++----- light-clients/ics10-grandpa-cw/src/context.rs | 55 ++++++++++++++++--- .../ics10-grandpa-cw/src/contract.rs | 46 +++++++++++++--- light-clients/ics10-grandpa-cw/src/msg.rs | 3 - 12 files changed, 284 insertions(+), 70 deletions(-) create mode 100644 light-clients/ics08-wasm/src/instantiate.rs diff --git a/light-clients/ics07-tendermint-cw/src/client.rs b/light-clients/ics07-tendermint-cw/src/client.rs index ed84b701a..9850cbcd4 100644 --- a/light-clients/ics07-tendermint-cw/src/client.rs +++ b/light-clients/ics07-tendermint-cw/src/client.rs @@ -27,6 +27,7 @@ use ibc::{ client_state::ClientType, context::{ClientKeeper, ClientReader, ClientTypes}, error::Error, + events::CodeId, }, ics24_host::identifier::ClientId, }, @@ -189,8 +190,29 @@ impl<'a, H: HostFunctionsProvider + 'static> ClientKeeper for Context<'a, H> { client_state: Self::AnyClientState, ) -> Result<(), Error> { let client_states = ReadonlyClientStates::new(self.storage()); - let data = client_states.get().ok_or_else(|| Error::client_not_found(client_id.clone()))?; - let encoded = Self::encode_client_state(client_state, data)?; + let code_id = match self.code_id.clone() { + None => { + let encoded_wasm_client_state = client_states + .get() + .ok_or_else(|| Error::client_not_found(client_id.clone()))?; + let any = Any::decode(&*encoded_wasm_client_state).map_err(Error::decode)?; + let wasm_client_state = ics08_wasm::client_state::ClientState::< + FakeInner, + FakeInner, + FakeInner, + >::decode_vec(&any.value) + .map_err(|e| { + Error::implementation_specific(format!( + "[client_state]: error decoding client state bytes to WasmConsensusState {}", + e + )) + })?; + wasm_client_state.code_id + }, + Some(x) => x, + }; + + let encoded = Self::encode_client_state(client_state, code_id)?; let mut client_state_storage = ClientStates::new(self.storage_mut()); client_state_storage.insert(encoded); Ok(()) @@ -277,19 +299,23 @@ impl<'a, H: Clone> Context<'a, H> { pub fn encode_client_state( client_state: ClientState, - encoded_wasm_client_state: Vec, + code_id: CodeId, + // encoded_wasm_client_state: Vec, ) -> Result, Error> { - let any = Any::decode(&*encoded_wasm_client_state).map_err(Error::decode)?; + // let any = Any::decode(&*encoded_wasm_client_state).map_err(Error::decode)?; + // let mut wasm_client_state = + // ics08_wasm::client_state::ClientState::::decode_vec( + // &any.value, + // ) + // .map_err(|e| { + // Error::implementation_specific(format!( + // "[client_state]: error decoding client state bytes to WasmConsensusState {}", + // e + // )) + // })?; let mut wasm_client_state = - ics08_wasm::client_state::ClientState::::decode_vec( - &any.value, - ) - .map_err(|e| { - Error::implementation_specific(format!( - "[client_state]: error decoding client state bytes to WasmConsensusState {}", - e - )) - })?; + ics08_wasm::client_state::ClientState::::default(); + wasm_client_state.code_id = code_id; wasm_client_state.data = client_state.to_any().encode_to_vec(); wasm_client_state.latest_height = client_state.latest_height().into(); let vec1 = wasm_client_state.to_any().encode_to_vec(); diff --git a/light-clients/ics07-tendermint-cw/src/context.rs b/light-clients/ics07-tendermint-cw/src/context.rs index 56b53353a..0003cec09 100644 --- a/light-clients/ics07-tendermint-cw/src/context.rs +++ b/light-clients/ics07-tendermint-cw/src/context.rs @@ -15,16 +15,21 @@ use crate::{ ics23::{ - ClientStates, ConsensusStates, ReadonlyClientStates, ReadonlyConsensusStates, + ClientStates, ConsensusStates, FakeInner, ReadonlyClientStates, ReadonlyConsensusStates, ReadonlyProcessedStates, }, ContractError, }; use cosmwasm_std::{DepsMut, Env, Storage}; use ibc::{ - core::{ics02_client::error::Error, ics26_routing::context::ReaderContext}, + core::{ + ics02_client::{error::Error, events::CodeId}, + ics24_host::identifier::ClientId, + ics26_routing::context::ReaderContext, + }, Height, }; +use ibc_proto::google::protobuf::Any; use ics07_tendermint::{ client_state::ClientState, consensus_state::ConsensusState, HostFunctionsProvider, }; @@ -33,6 +38,7 @@ use std::{fmt, fmt::Debug, marker::PhantomData}; pub struct Context<'a, H> { pub deps: DepsMut<'a>, pub env: Env, + pub code_id: Option, _phantom: PhantomData, } @@ -58,7 +64,7 @@ impl<'a, H> Clone for Context<'a, H> { impl<'a, H> Context<'a, H> { pub fn new(deps: DepsMut<'a>, env: Env) -> Self { - Self { deps, _phantom: Default::default(), env } + Self { deps, _phantom: Default::default(), env, code_id: None } } pub fn log(&self, msg: &str) { @@ -141,11 +147,42 @@ where client_state: ClientState, prefix: &[u8], ) -> Result<(), ContractError> { + use prost::Message; + use tendermint_proto::Protobuf; let client_states = ReadonlyClientStates::new(self.storage()); - let data = client_states.get_prefixed(prefix).ok_or_else(|| { - ContractError::Tendermint("no client state found for prefix".to_string()) - })?; - let encoded = Context::::encode_client_state(client_state, data).map_err(|e| { + // let data = client_states.get_prefixed(prefix).ok_or_else(|| { + // ContractError::Tendermint("no client state found for prefix".to_string()) + // })?; + let code_id = match self.code_id.clone() { + None => { + let encoded_wasm_client_state = client_states.get().ok_or_else(|| { + ContractError::Tendermint( + Error::client_not_found(ClientId::new("x", 1).unwrap()).to_string(), + ) + })?; + let any = Any::decode(&*encoded_wasm_client_state) + .map_err(Error::decode) + .map_err(|e| ContractError::Tendermint(e.to_string()))?; + let wasm_client_state = ics08_wasm::client_state::ClientState::< + FakeInner, + FakeInner, + FakeInner, + >::decode_vec(&any.value) + .map_err(|e| { + ContractError::Tendermint( + Error::implementation_specific(format!( + "[client_state]: error decoding client state bytes to WasmConsensusState {}", + e + )) + .to_string(), + ) + })?; + wasm_client_state.code_id + }, + Some(x) => x, + }; + + let encoded = Context::::encode_client_state(client_state, code_id).map_err(|e| { ContractError::Tendermint(format!("error encoding client state: {:?}", e)) })?; let mut client_states = ClientStates::new(self.storage_mut()); diff --git a/light-clients/ics07-tendermint-cw/src/contract.rs b/light-clients/ics07-tendermint-cw/src/contract.rs index 944b6ccbb..53590d83e 100644 --- a/light-clients/ics07-tendermint-cw/src/contract.rs +++ b/light-clients/ics07-tendermint-cw/src/contract.rs @@ -20,10 +20,10 @@ use crate::{ check_substitute_and_update_state, prune_oldest_consensus_state, verify_delay_passed, verify_upgrade_and_update_state, }, - ics23::ReadonlyProcessedStates, + ics23::{FakeInner, ReadonlyProcessedStates}, msg::{ - CheckForMisbehaviourMsg, ContractResult, ExecuteMsg, ExportMetadataMsg, InstantiateMsg, - QueryMsg, QueryResponse, StatusMsg, UpdateStateMsg, UpdateStateOnMisbehaviourMsg, + CheckForMisbehaviourMsg, ContractResult, ExecuteMsg, ExportMetadataMsg, QueryMsg, + QueryResponse, StatusMsg, UpdateStateMsg, UpdateStateOnMisbehaviourMsg, VerifyClientMessage, VerifyMembershipMsg, VerifyNonMembershipMsg, VerifyUpgradeAndUpdateStateMsg, }, @@ -40,11 +40,15 @@ use ibc::core::{ }, ics24_host::identifier::ClientId, }; +use ibc_proto::google::protobuf::Any; use ics07_tendermint::{ client_def::{verify_membership, verify_non_membership, TendermintClient}, + client_state::ClientState, + consensus_state::ConsensusState, HostFunctionsProvider, }; -use ics08_wasm::SUBJECT_PREFIX; +use ics08_wasm::{instantiate::InstantiateMessage, SUBJECT_PREFIX}; +use prost::Message; use sha2::{Digest, Sha256}; use std::str::FromStr; use tendermint::{ @@ -56,6 +60,7 @@ use tendermint::{ PublicKey, Signature, }; use tendermint_light_client_verifier::operations::CommitValidator; +use tendermint_proto::Protobuf; #[derive(Clone, Copy, Debug, PartialEq, Default, Eq)] pub struct HostFunctions; @@ -121,25 +126,44 @@ impl Verifier for HostFunctions { impl CommitValidator for HostFunctions {} impl HostFunctionsProvider for HostFunctions {} +fn process_instantiate_msg( + msg: InstantiateMessage, + ctx: &mut Context, + client_id: ClientId, +) -> Result { + let any = Any::decode(&mut msg.client_state.data.as_slice())?; + let client_state = ClientState::decode_vec(&any.value)?; + let any = Any::decode(&mut msg.consensus_state.data.as_slice())?; + let consensus_state = ConsensusState::decode_vec(&any.value)?; + + ctx.code_id = Some(msg.client_state.code_id); + let height = client_state.latest_height(); + ctx.store_client_state(client_id.clone(), client_state) + .map_err(|e| ContractError::Tendermint(e.to_string()))?; + ctx.store_consensus_state(client_id.clone(), height, consensus_state) + .map_err(|e| ContractError::Tendermint(e.to_string()))?; + + ctx.store_update_height(client_id.clone(), height, ctx.host_height()) + .map_err(|e| ContractError::Tendermint(e.to_string()))?; + ctx.store_update_time(client_id, height, ctx.host_timestamp()) + .map_err(|e| ContractError::Tendermint(e.to_string()))?; + + Ok(to_binary(&ContractResult::success())?) +} + #[cfg_attr(not(feature = "library"), entry_point)] pub fn instantiate( deps: DepsMut, env: Env, _info: MessageInfo, - _msg: InstantiateMsg, + msg: InstantiateMessage, ) -> Result { - let _client = TendermintClient::::default(); let mut ctx = Context::::new(deps, env); let client_id = ClientId::from_str("08-wasm-0").expect("client id is valid"); - let client_state = ctx - .client_state(&client_id.clone()) - .map_err(|e| ContractError::Tendermint(e.to_string()))?; - ctx.store_update_height(client_id.clone(), client_state.latest_height, ctx.host_height()) - .map_err(|e| ContractError::Tendermint(e.to_string()))?; - ctx.store_update_time(client_id.clone(), client_state.latest_height, ctx.host_timestamp()) - .map_err(|e| ContractError::Tendermint(e.to_string()))?; - - Ok(Response::default()) + let data = process_instantiate_msg(msg, &mut ctx, client_id.clone())?; + let mut response = Response::default(); + response.data = Some(data); + Ok(response) } #[cfg_attr(not(feature = "library"), entry_point)] diff --git a/light-clients/ics07-tendermint-cw/src/msg.rs b/light-clients/ics07-tendermint-cw/src/msg.rs index b500e7344..cc83e8100 100644 --- a/light-clients/ics07-tendermint-cw/src/msg.rs +++ b/light-clients/ics07-tendermint-cw/src/msg.rs @@ -101,9 +101,6 @@ impl ContractResult { } } -#[cw_serde] -pub struct InstantiateMsg {} - #[cw_serde] pub enum ExecuteMsg { VerifyMembership(VerifyMembershipMsgRaw), diff --git a/light-clients/ics08-wasm/src/client_state.rs b/light-clients/ics08-wasm/src/client_state.rs index 03f6910b4..d9074ae33 100644 --- a/light-clients/ics08-wasm/src/client_state.rs +++ b/light-clients/ics08-wasm/src/client_state.rs @@ -202,3 +202,17 @@ where AnyClient: Clone, { } + +impl Default + for ClientState +{ + fn default() -> Self { + ClientState { + data: vec![], + code_id: vec![], + latest_height: Default::default(), + inner: Box::new(AnyClientState::default()), + _phantom: Default::default(), + } + } +} diff --git a/light-clients/ics08-wasm/src/consensus_state.rs b/light-clients/ics08-wasm/src/consensus_state.rs index 83d678337..cbc1b7cda 100644 --- a/light-clients/ics08-wasm/src/consensus_state.rs +++ b/light-clients/ics08-wasm/src/consensus_state.rs @@ -122,3 +122,9 @@ where >::Error: Display, { } + +impl Default for ConsensusState { + fn default() -> Self { + ConsensusState { data: vec![], timestamp: 0, inner: Box::new(AnyConsensusState::default()) } + } +} diff --git a/light-clients/ics08-wasm/src/instantiate.rs b/light-clients/ics08-wasm/src/instantiate.rs new file mode 100644 index 000000000..4e8bad55c --- /dev/null +++ b/light-clients/ics08-wasm/src/instantiate.rs @@ -0,0 +1,15 @@ +use super::client_state::ClientState; +use crate::consensus_state::ConsensusState; +use cosmwasm_schema::cw_serde; + +#[cfg_attr(feature = "cosmwasm", cw_serde)] +#[cfg_attr(not(feature = "cosmwasm"), derive(Clone, Debug, PartialEq))] +#[derive(Eq)] +pub struct InstantiateMessage< + AnyClient: Default, + AnyClientState: Default, + AnyConsensusState: Default, +> { + pub client_state: ClientState, + pub consensus_state: ConsensusState, +} diff --git a/light-clients/ics08-wasm/src/lib.rs b/light-clients/ics08-wasm/src/lib.rs index 4070ece03..9cc2b5a1d 100644 --- a/light-clients/ics08-wasm/src/lib.rs +++ b/light-clients/ics08-wasm/src/lib.rs @@ -24,6 +24,7 @@ pub mod client_def; pub mod client_message; pub mod client_state; pub mod consensus_state; +pub mod instantiate; pub mod msg; pub type Bytes = Vec; diff --git a/light-clients/ics10-grandpa-cw/src/client.rs b/light-clients/ics10-grandpa-cw/src/client.rs index 53fc74080..a85726bd5 100644 --- a/light-clients/ics10-grandpa-cw/src/client.rs +++ b/light-clients/ics10-grandpa-cw/src/client.rs @@ -30,6 +30,7 @@ use ibc::{ client_state::ClientType, context::{ClientKeeper, ClientReader, ClientTypes}, error::Error, + events::CodeId, }, ics24_host::identifier::ClientId, }, @@ -198,8 +199,31 @@ impl<'a, H: HostFunctions
> ClientKeeper for Context<' ) -> Result<(), Error> { log!(self, "in client : [store_client_state]"); let client_states = ReadonlyClientStates::new(self.storage()); - let data = client_states.get().ok_or_else(|| Error::client_not_found(client_id.clone()))?; - let vec1 = Self::encode_client_state(client_state, data)?; + // let data = client_states.get().ok_or_else(|| + // Error::client_not_found(client_id.clone()))?; + let code_id = match self.code_id.clone() { + None => { + let encoded_wasm_client_state = client_states + .get() + .ok_or_else(|| Error::client_not_found(client_id.clone()))?; + let any = Any::decode(&*encoded_wasm_client_state).map_err(Error::decode)?; + let wasm_client_state = ics08_wasm::client_state::ClientState::< + FakeInner, + FakeInner, + FakeInner, + >::decode_vec(&any.value) + .map_err(|e| { + Error::implementation_specific(format!( + "[client_state]: error decoding client state bytes to WasmConsensusState {}", + e + )) + })?; + wasm_client_state.code_id + }, + Some(x) => x, + }; + + let vec1 = Self::encode_client_state(client_state, code_id)?; log!(self, "in cliden : [store_client_state] >> wasm client state (raw)"); let mut client_state_storage = ClientStates::new(self.storage_mut()); client_state_storage.insert(vec1); @@ -289,19 +313,23 @@ impl<'a, H: Clone> Context<'a, H> { pub fn encode_client_state( client_state: ClientState, - encoded_wasm_client_state: Vec, + code_id: CodeId, + // encoded_wasm_client_state: Vec, ) -> Result, Error> { - let any = Any::decode(&*encoded_wasm_client_state).map_err(Error::decode)?; + // let any = Any::decode(&*encoded_wasm_client_state).map_err(Error::decode)?; + // let mut wasm_client_state = + // ics08_wasm::client_state::ClientState::::decode_vec( + // &any.value, + // ) + // .map_err(|e| { + // Error::implementation_specific(format!( + // "[client_state]: error decoding client state bytes to WasmConsensusState {}", + // e + // )) + // })?; let mut wasm_client_state = - ics08_wasm::client_state::ClientState::::decode_vec( - &any.value, - ) - .map_err(|e| { - Error::implementation_specific(format!( - "[client_state]: error decoding client state bytes to WasmConsensusState {}", - e - )) - })?; + ics08_wasm::client_state::ClientState::::default(); + wasm_client_state.code_id = code_id; wasm_client_state.data = client_state.to_any().encode_to_vec(); wasm_client_state.latest_height = client_state.latest_height().into(); let vec1 = wasm_client_state.to_any().encode_to_vec(); diff --git a/light-clients/ics10-grandpa-cw/src/context.rs b/light-clients/ics10-grandpa-cw/src/context.rs index 523c0a982..48a068ade 100644 --- a/light-clients/ics10-grandpa-cw/src/context.rs +++ b/light-clients/ics10-grandpa-cw/src/context.rs @@ -18,12 +18,22 @@ use crate::{ GRANDPA_BLOCK_HASHES_CACHE_SIZE, GRANDPA_HEADER_HASHES_SET_STORAGE, GRANDPA_HEADER_HASHES_STORAGE, }, - ics23::{ClientStates, ConsensusStates, ReadonlyClientStates, ReadonlyConsensusStates}, + ics23::{ + ClientStates, ConsensusStates, FakeInner, ReadonlyClientStates, ReadonlyConsensusStates, + }, ContractError, }; use cosmwasm_std::{DepsMut, Env, Storage}; use grandpa_light_client_primitives::HostFunctions; -use ibc::{core::ics26_routing::context::ReaderContext, Height}; +use ibc::{ + core::{ + ics02_client::{error::Error, events::CodeId}, + ics24_host::identifier::ClientId, + ics26_routing::context::ReaderContext, + }, + Height, +}; +use ibc_proto::google::protobuf::Any; use ics10_grandpa::{ client_message::RelayChainHeader, client_state::ClientState, consensus_state::ConsensusState, }; @@ -33,6 +43,7 @@ use std::{fmt, fmt::Debug, marker::PhantomData}; pub struct Context<'a, H> { pub deps: DepsMut<'a>, pub env: Env, + pub code_id: Option, _phantom: PhantomData, } @@ -58,7 +69,7 @@ impl<'a, H> Clone for Context<'a, H> { impl<'a, H> Context<'a, H> { pub fn new(deps: DepsMut<'a>, env: Env) -> Self { - Self { deps, _phantom: Default::default(), env } + Self { deps, _phantom: Default::default(), env, code_id: None } } pub fn log(&self, msg: &str) { @@ -153,11 +164,41 @@ where client_state: ClientState, prefix: &[u8], ) -> Result<(), ContractError> { + use prost::Message; + use tendermint_proto::Protobuf; let client_states = ReadonlyClientStates::new(self.storage()); - let data = client_states.get_prefixed(prefix).ok_or_else(|| { - ContractError::Grandpa("no client state found for prefix".to_string()) - })?; - let encoded = Context::::encode_client_state(client_state, data) + // let data = client_states.get_prefixed(prefix).ok_or_else(|| { + // ContractError::Tendermint("no client state found for prefix".to_string()) + // })?; + let code_id = match self.code_id.clone() { + None => { + let encoded_wasm_client_state = client_states.get().ok_or_else(|| { + ContractError::Grandpa( + Error::client_not_found(ClientId::new("x", 1).unwrap()).to_string(), + ) + })?; + let any = Any::decode(&*encoded_wasm_client_state) + .map_err(Error::decode) + .map_err(|e| ContractError::Grandpa(e.to_string()))?; + let wasm_client_state = ics08_wasm::client_state::ClientState::< + FakeInner, + FakeInner, + FakeInner, + >::decode_vec(&any.value) + .map_err(|e| { + ContractError::Grandpa( + Error::implementation_specific(format!( + "[client_state]: error decoding client state bytes to WasmConsensusState {}", + e + )) + .to_string(), + ) + })?; + wasm_client_state.code_id + }, + Some(x) => x, + }; + let encoded = Context::::encode_client_state(client_state, code_id) .map_err(|e| ContractError::Grandpa(format!("error encoding client state: {:?}", e)))?; let mut client_states = ClientStates::new(self.storage_mut()); client_states.insert_prefixed(encoded, prefix); diff --git a/light-clients/ics10-grandpa-cw/src/contract.rs b/light-clients/ics10-grandpa-cw/src/contract.rs index 673a3db14..cf753ad72 100644 --- a/light-clients/ics10-grandpa-cw/src/contract.rs +++ b/light-clients/ics10-grandpa-cw/src/contract.rs @@ -16,13 +16,13 @@ use crate::{ context::Context, error::ContractError, + ics23::FakeInner, log, msg::{ CheckForMisbehaviourMsg, CheckSubstituteAndUpdateStateMsg, ClientStateCallResponse, - ContractResult, ExecuteMsg, ExportMetadataMsg, InitializeState, InstantiateMsg, QueryMsg, - QueryResponse, StatusMsg, UpdateStateMsg, UpdateStateOnMisbehaviourMsg, - VerifyClientMessage, VerifyMembershipMsg, VerifyNonMembershipMsg, - VerifyUpgradeAndUpdateStateMsg, + ContractResult, ExecuteMsg, ExportMetadataMsg, InitializeState, QueryMsg, QueryResponse, + StatusMsg, UpdateStateMsg, UpdateStateOnMisbehaviourMsg, VerifyClientMessage, + VerifyMembershipMsg, VerifyNonMembershipMsg, VerifyUpgradeAndUpdateStateMsg, }, state::{get_client_state, get_consensus_state}, Bytes, @@ -43,7 +43,8 @@ use ibc::core::{ }, ics24_host::identifier::ClientId, }; -use ics08_wasm::{SUBJECT_PREFIX, SUBSTITUTE_PREFIX}; +use ibc_proto::google::protobuf::Any; +use ics08_wasm::{instantiate::InstantiateMessage, SUBJECT_PREFIX, SUBSTITUTE_PREFIX}; use ics10_grandpa::{ client_def::GrandpaClient, client_message::{ClientMessage, RelayChainHeader}, @@ -51,10 +52,12 @@ use ics10_grandpa::{ consensus_state::ConsensusState, }; use light_client_common::{verify_membership, verify_non_membership}; +use prost::Message; use sp_core::H256; use sp_runtime::traits::{BlakeTwo256, Header}; use sp_runtime_interface::unpack_ptr_and_len; use std::{collections::BTreeSet, str::FromStr}; +use tendermint_proto::Protobuf; /* // version info for migration info const CONTRACT_NAME: &str = "crates.io:ics10-grandpa-cw"; @@ -114,14 +117,39 @@ impl grandpa_light_client_primitives::HostFunctions for HostFunctions { } } +fn process_instantiate_msg( + msg: InstantiateMessage, + ctx: &mut Context, + client_id: ClientId, +) -> Result { + let any = Any::decode(&mut msg.client_state.data.as_slice())?; + let client_state = ClientState::decode_vec(&any.value)?; + let any = Any::decode(&mut msg.consensus_state.data.as_slice())?; + let consensus_state = ConsensusState::decode_vec(&any.value)?; + + let height = client_state.latest_height(); + ctx.code_id = Some(msg.client_state.code_id); + ctx.store_client_state(client_id.clone(), client_state) + .map_err(|e| ContractError::Grandpa(e.to_string()))?; + ctx.store_consensus_state(client_id, height, consensus_state) + .map_err(|e| ContractError::Grandpa(e.to_string()))?; + Ok(to_binary(&ContractResult::success())?) +} + #[cfg_attr(not(feature = "library"), entry_point)] pub fn instantiate( - _deps: DepsMut, - _env: Env, + deps: DepsMut, + env: Env, _info: MessageInfo, - _msg: InstantiateMsg, + msg: InstantiateMessage, ) -> Result { - Ok(Response::default()) + let mut ctx = Context::::new(deps, env); + let client_id = ClientId::from_str("08-wasm-0").expect("client id is valid"); + let data = process_instantiate_msg(msg, &mut ctx, client_id.clone())?; + + let mut response = Response::default(); + response.data = Some(data); + Ok(response) } #[cfg_attr(not(feature = "library"), entry_point)] diff --git a/light-clients/ics10-grandpa-cw/src/msg.rs b/light-clients/ics10-grandpa-cw/src/msg.rs index f9ba87892..b90433c17 100644 --- a/light-clients/ics10-grandpa-cw/src/msg.rs +++ b/light-clients/ics10-grandpa-cw/src/msg.rs @@ -115,9 +115,6 @@ pub struct InitializeState { pub consensus_state: WasmConsensusState, } -#[cw_serde] -pub struct InstantiateMsg {} - #[cw_serde] pub struct ClientCreateRequest { client_create_request: WasmConsensusState, From 767e060e80c8320c0f41f4ba43be8693feac1c94 Mon Sep 17 00:00:00 2001 From: Vladislav Markushin Date: Fri, 21 Jul 2023 17:46:31 -0300 Subject: [PATCH 02/37] wip --- .../src/prost/ibc.lightclients.wasm.v1.rs | 8 ++++---- .../ics08-wasm/src/consensus_state.rs | 19 +++++++++++-------- light-clients/ics10-grandpa-cw/src/client.rs | 1 - 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/ibc/proto/src/prost/ibc.lightclients.wasm.v1.rs b/ibc/proto/src/prost/ibc.lightclients.wasm.v1.rs index 69b4ef2a0..2504bf8f9 100644 --- a/ibc/proto/src/prost/ibc.lightclients.wasm.v1.rs +++ b/ibc/proto/src/prost/ibc.lightclients.wasm.v1.rs @@ -485,10 +485,10 @@ pub struct ClientState { pub struct ConsensusState { #[prost(bytes = "vec", tag = "1")] pub data: ::prost::alloc::vec::Vec, - /// timestamp that corresponds to the block height in which the ConsensusState - /// was stored. - #[prost(uint64, tag = "2")] - pub timestamp: u64, + // timestamp that corresponds to the block height in which the ConsensusState + // was stored. + // #[prost(uint64, tag = "2")] + // pub timestamp: u64, } /// Wasm light client Header #[allow(clippy::derive_partial_eq_without_eq)] diff --git a/light-clients/ics08-wasm/src/consensus_state.rs b/light-clients/ics08-wasm/src/consensus_state.rs index cbc1b7cda..9f710e411 100644 --- a/light-clients/ics08-wasm/src/consensus_state.rs +++ b/light-clients/ics08-wasm/src/consensus_state.rs @@ -29,7 +29,10 @@ use core::{ use cosmwasm_schema::cw_serde; use ibc::{ core::{ - ics02_client::client_consensus::ConsensusState as IbcConsensusState, + ics02_client::client_consensus::{ + ConsensusState as IcsConsensusState, ConsensusState as _, + ConsensusState as IbcConsensusState, + }, ics23_commitment::commitment::CommitmentRoot, }, protobuf::Protobuf, @@ -49,7 +52,6 @@ pub struct ConsensusState { #[cfg_attr(feature = "cosmwasm", schemars(with = "String"))] #[cfg_attr(feature = "cosmwasm", serde(with = "Base64", default))] pub data: Bytes, - pub timestamp: u64, #[cfg_attr(feature = "cosmwasm", serde(skip))] #[cfg_attr(feature = "cosmwasm", schemars(skip))] pub inner: Box, @@ -68,7 +70,7 @@ where } fn timestamp(&self) -> Timestamp { - Timestamp::from_nanoseconds(self.timestamp).expect("timestamp is valid") + self.inner.timestamp() } fn encode_to_vec(&self) -> Result, tendermint_proto::Error> { @@ -105,20 +107,21 @@ where let inner = AnyConsensusState::try_from(any).map_err(|e| { format!("failed to decode ConsensusState::data into ConsensusState: {}", e) })?; - Ok(Self { data: raw.data, timestamp: raw.timestamp, inner: Box::new(inner) }) + Ok(Self { data: raw.data, inner: Box::new(inner) }) } } -impl From> for RawConsensusState { +impl From> + for RawConsensusState +{ fn from(value: ConsensusState) -> Self { - Self { data: value.data, timestamp: value.timestamp } + Self { data: value.data } } } impl Protobuf for ConsensusState where - AnyConsensusState: Clone, - AnyConsensusState: TryFrom, + AnyConsensusState: Clone + IbcConsensusState + TryFrom, >::Error: Display, { } diff --git a/light-clients/ics10-grandpa-cw/src/client.rs b/light-clients/ics10-grandpa-cw/src/client.rs index a85726bd5..ee35189bb 100644 --- a/light-clients/ics10-grandpa-cw/src/client.rs +++ b/light-clients/ics10-grandpa-cw/src/client.rs @@ -339,7 +339,6 @@ impl<'a, H: Clone> Context<'a, H> { pub fn encode_consensus_state(consensus_state: ConsensusState) -> Vec { let wasm_consensus_state = ics08_wasm::consensus_state::ConsensusState { data: consensus_state.to_any().encode_to_vec(), - timestamp: consensus_state.timestamp().nanoseconds(), inner: Box::new(FakeInner), }; wasm_consensus_state.to_any().encode_to_vec() From 19759a63331dbd42248325f326dfd725211259a5 Mon Sep 17 00:00:00 2001 From: Steve Miskovetz Date: Sun, 6 Aug 2023 12:48:28 -0600 Subject: [PATCH 03/37] Change code_id to code_hash --- contracts/pallet-ibc/src/client.rs | 4 ++-- contracts/pallet-ibc/src/events.rs | 12 +++++----- contracts/pallet-ibc/src/light_clients.rs | 5 ++-- hyperspace/core/src/chain.rs | 8 +++---- hyperspace/core/src/command.rs | 8 +++---- hyperspace/core/src/macros.rs | 24 +++++++++---------- hyperspace/core/src/substrate/macros.rs | 4 ++-- hyperspace/cosmos/src/client.rs | 2 +- hyperspace/cosmos/src/events.rs | 10 ++++---- hyperspace/cosmos/src/provider.rs | 4 ++-- hyperspace/parachain/src/lib.rs | 2 +- hyperspace/parachain/src/provider.rs | 6 ++--- .../testsuite/tests/parachain_cosmos.rs | 12 +++++----- .../testsuite/tests/parachain_parachain.rs | 4 ++-- ibc/modules/src/core/ics02_client/events.rs | 6 ++--- .../src/prost/ibc.lightclients.wasm.v1.rs | 6 ++--- .../ics07-tendermint-cw/src/client.rs | 13 +++++----- .../ics07-tendermint-cw/src/context.rs | 12 +++++----- .../ics07-tendermint-cw/src/contract.rs | 2 +- light-clients/ics08-wasm/src/client_def.rs | 8 +++---- light-clients/ics08-wasm/src/client_state.rs | 8 +++---- .../ics08-wasm/src/consensus_state.rs | 4 ++-- light-clients/ics10-grandpa-cw/src/client.rs | 12 +++++----- light-clients/ics10-grandpa-cw/src/context.rs | 12 +++++----- .../ics10-grandpa-cw/src/contract.rs | 2 +- 25 files changed, 94 insertions(+), 96 deletions(-) diff --git a/contracts/pallet-ibc/src/client.rs b/contracts/pallet-ibc/src/client.rs index 76da5e77b..f22f5dcea 100644 --- a/contracts/pallet-ibc/src/client.rs +++ b/contracts/pallet-ibc/src/client.rs @@ -30,7 +30,7 @@ pub struct HostConsensusProof { pub header: Vec, pub extrinsic: Vec, pub extrinsic_proof: Vec>, - pub code_id: Option>, + pub code_hash: Option>, } impl ClientReader for Context @@ -295,7 +295,7 @@ where AnyConsensusState::wasm(cs).map_err(ICS02Error::encode)? }, _ => - if let Some(_) = connection_proof.code_id { + if let Some(_) = connection_proof.code_hash { log::trace!(target: "pallet_ibc", "in client : [host_consensus_state] >> using wasm code id"); AnyConsensusState::wasm(cs).map_err(ICS02Error::encode)? } else { diff --git a/contracts/pallet-ibc/src/events.rs b/contracts/pallet-ibc/src/events.rs index b32391396..97c5ddbc5 100644 --- a/contracts/pallet-ibc/src/events.rs +++ b/contracts/pallet-ibc/src/events.rs @@ -4,7 +4,7 @@ use ibc::{ core::{ ics02_client::{ events as ClientEvents, - events::{CodeId, NewBlock}, + events::{CodeHash, NewBlock}, }, ics03_connection::events as ConnectionEvents, ics04_channel::{events as ChannelEvents, packet::Packet}, @@ -218,7 +218,7 @@ pub enum IbcEvent { /// App module AppModule { kind: Vec, module_id: Vec }, /// Push WASM Code - PushWasmCode { wasm_code_id: CodeId }, + PushWasmCode { wasm_code_hash: CodeHash }, } impl From for IbcEvent { @@ -439,8 +439,8 @@ impl From for IbcEvent { module_id: ev.module_name.to_string().as_bytes().to_vec(), }, RawIbcEvent::PushWasmCode(ev) => { - let wasm_code_id = ev.0; - IbcEvent::PushWasmCode { wasm_code_id } + let wasm_code_hash = ev.0; + IbcEvent::PushWasmCode { wasm_code_hash } }, } } @@ -545,8 +545,8 @@ impl TryFrom for RawIbcEvent { consensus_height: Height::new(consensus_revision_number, consensus_height), }, ))), - IbcEvent::PushWasmCode { wasm_code_id } => - Ok(RawIbcEvent::PushWasmCode(ClientEvents::PushWasmCode(wasm_code_id))), + IbcEvent::PushWasmCode { wasm_code_hash } => + Ok(RawIbcEvent::PushWasmCode(ClientEvents::PushWasmCode(wasm_code_hash))), IbcEvent::OpenInitConnection { revision_height, revision_number, diff --git a/contracts/pallet-ibc/src/light_clients.rs b/contracts/pallet-ibc/src/light_clients.rs index 3b085a1d2..fdf99403c 100644 --- a/contracts/pallet-ibc/src/light_clients.rs +++ b/contracts/pallet-ibc/src/light_clients.rs @@ -279,13 +279,13 @@ impl AnyClientState { } impl AnyClientState { - pub fn wasm(inner: Self, code_id: Bytes) -> Result { + pub fn wasm(inner: Self, code_hash: Bytes) -> Result { Ok(Self::Wasm( ics08_wasm::client_state::ClientState:: { data: inner.encode_to_vec()?, latest_height: inner.latest_height(), inner: Box::new(inner), - code_id, + code_hash, _phantom: Default::default(), }, )) @@ -310,7 +310,6 @@ pub enum AnyConsensusState { impl AnyConsensusState { pub fn wasm(inner: Self) -> Result { Ok(Self::Wasm(ics08_wasm::consensus_state::ConsensusState { - timestamp: inner.timestamp().nanoseconds(), data: inner.encode_to_vec()?, inner: Box::new(inner), })) diff --git a/hyperspace/core/src/chain.rs b/hyperspace/core/src/chain.rs index a19c3182d..4500c4d1b 100644 --- a/hyperspace/core/src/chain.rs +++ b/hyperspace/core/src/chain.rs @@ -31,7 +31,7 @@ use ibc::{ core::{ ics02_client::{ client_state::ClientType, - events::{CodeId, UpdateClient}, + events::{CodeHash, UpdateClient}, msgs::{create_client::MsgCreateAnyClient, update_client::MsgUpdateAnyClient}, }, ics03_connection::msgs::{ @@ -101,7 +101,7 @@ chains! { Cosmos(CosmosClientConfig, CosmosClient), } -fn wrap_any_msg_into_wasm(msg: Any, code_id: Bytes) -> Result { +fn wrap_any_msg_into_wasm(msg: Any, code_hash: Bytes) -> Result { // TODO: consider rewriting with Ics26Envelope use ibc::core::{ ics02_client::msgs::{ @@ -119,7 +119,7 @@ fn wrap_any_msg_into_wasm(msg: Any, code_id: Bytes) -> Result::decode_vec(&msg.value).unwrap(); msg_decoded.consensus_state = AnyConsensusState::wasm(msg_decoded.consensus_state)?; - msg_decoded.client_state = AnyClientState::wasm(msg_decoded.client_state, code_id)?; + msg_decoded.client_state = AnyClientState::wasm(msg_decoded.client_state, code_hash)?; msg_decoded.to_any() }, CONN_OPEN_TRY_TYPE_URL => { @@ -147,5 +147,5 @@ fn wrap_any_msg_into_wasm(msg: Any, code_id: Bytes) -> Result, - pub code_id: Bytes, + pub code_hash: Bytes, } diff --git a/hyperspace/core/src/command.rs b/hyperspace/core/src/command.rs index 8c5644c91..b5a75c2ab 100644 --- a/hyperspace/core/src/command.rs +++ b/hyperspace/core/src/command.rs @@ -105,10 +105,10 @@ impl UploadWasmCmd { let mut config: AnyConfig = toml::from_str(&file_content)?; let client = config.clone().into_client().await?; let wasm = tokio::fs::read(&self.wasm_path).await?; - let code_id = client.upload_wasm(wasm).await?; - let code_id_str = hex::encode(&code_id); - println!("{}", code_id_str); - config.set_wasm_code_id(code_id_str); + let code_hash = client.upload_wasm(wasm).await?; + let code_hash_str = hex::encode(&code_hash); + println!("{}", code_hash_str); + config.set_wasm_code_hash(code_hash_str); Ok(config) } diff --git a/hyperspace/core/src/macros.rs b/hyperspace/core/src/macros.rs index c9f361d09..d8ae60126 100644 --- a/hyperspace/core/src/macros.rs +++ b/hyperspace/core/src/macros.rs @@ -807,7 +807,7 @@ macro_rules! chains { Self::Wasm(chain) => { let messages = messages .into_iter() - .map(|msg| wrap_any_msg_into_wasm(msg, chain.code_id.clone())) + .map(|msg| wrap_any_msg_into_wasm(msg, chain.code_hash.clone())) .collect::, _>>()?; chain.inner.submit(messages).await.map_err(AnyError::into) }, @@ -988,15 +988,15 @@ macro_rules! chains { impl AnyConfig { pub async fn into_client(self) -> anyhow::Result { - let maybe_wasm_code_id = self.wasm_code_id(); + let maybe_wasm_code_hash = self.wasm_code_hash(); let chain = match self { $( $(#[$($meta)*])* AnyConfig::$name(config) => AnyChain::$name(<$client>::new(config).await?), )* }; - if let Some(code_id) = maybe_wasm_code_id { - Ok(AnyChain::Wasm(WasmChain { inner: Box::new(chain), code_id })) + if let Some(code_hash) = maybe_wasm_code_hash { + Ok(AnyChain::Wasm(WasmChain { inner: Box::new(chain), code_hash })) } else { Ok(chain) } @@ -1035,25 +1035,25 @@ macro_rules! chains { } } - pub fn wasm_code_id(&self) -> Option { - let maybe_code_id = match self { + pub fn wasm_code_hash(&self) -> Option { + let maybe_code_hash = match self { $( $(#[$($meta)*])* - Self::$name(chain) => chain.wasm_code_id.as_ref(), + Self::$name(chain) => chain.wasm_code_hash.as_ref(), )* }; - let maybe_code_id = - maybe_code_id.map(|s| hex::decode(s).expect("Wasm code id is hex-encoded")); + let maybe_code_hash = + maybe_code_hash.map(|s| hex::decode(s).expect("Wasm code id is hex-encoded")); - maybe_code_id + maybe_code_hash } - pub fn set_wasm_code_id(&mut self, code_id: String) { + pub fn set_wasm_code_hash(&mut self, code_hash: String) { match self { $( $(#[$($meta)*])* Self::$name(chain) => { - chain.wasm_code_id = Some(code_id); + chain.wasm_code_hash = Some(code_hash); }, )* } diff --git a/hyperspace/core/src/substrate/macros.rs b/hyperspace/core/src/substrate/macros.rs index e47e57459..aed1b79b5 100644 --- a/hyperspace/core/src/substrate/macros.rs +++ b/hyperspace/core/src/substrate/macros.rs @@ -487,8 +487,8 @@ macro_rules! define_ibc_event_wrapper { RawIbcEvent::AppModule { kind, module_id }, MetadataIbcEvent::Empty => RawIbcEvent::Empty, MetadataIbcEvent::ChainError => RawIbcEvent::ChainError, - MetadataIbcEvent::PushWasmCode{ wasm_code_id } => RawIbcEvent::PushWasmCode { - wasm_code_id + MetadataIbcEvent::PushWasmCode{ wasm_code_hash } => RawIbcEvent::PushWasmCode { + wasm_code_hash }, $($additional)* } diff --git a/hyperspace/cosmos/src/client.rs b/hyperspace/cosmos/src/client.rs index acd2f67bb..4b54e4ef5 100644 --- a/hyperspace/cosmos/src/client.rs +++ b/hyperspace/cosmos/src/client.rs @@ -212,7 +212,7 @@ pub struct CosmosClientConfig { pub max_tx_size: usize, /// All the client states and headers will be wrapped in WASM ones using the WASM code ID. #[serde(default)] - pub wasm_code_id: Option, + pub wasm_code_hash: Option, /* Here is a list of dropped configuration parameters from Hermes Config.toml that could be set to default values or removed for the MVP phase: diff --git a/hyperspace/cosmos/src/events.rs b/hyperspace/cosmos/src/events.rs index 36ad38243..094dfec3d 100644 --- a/hyperspace/cosmos/src/events.rs +++ b/hyperspace/cosmos/src/events.rs @@ -211,19 +211,19 @@ pub fn client_misbehaviour_try_from_abci_event( pub fn push_wasm_code_try_from_abci_event( abci_event: &AbciEvent, ) -> Result { - let mut code_id = None; + let mut code_hash = None; for tag in &abci_event.attributes { let key = tag.key.as_str(); let value = tag.value.as_str(); match key { - client_events::WASM_CODE_ID_ATTRIBUTE_KEY => - code_id = Some(hex::decode(value).map_err(IbcEventError::from_hex_error)?), + client_events::WASM_CODE_HASH_ATTRIBUTE_KEY => + code_hash = Some(hex::decode(value).map_err(IbcEventError::from_hex_error)?), _ => {}, } } - Ok(client_events::PushWasmCode(code_id.ok_or_else(|| { - IbcEventError::missing_key(client_events::WASM_CODE_ID_ATTRIBUTE_KEY.to_owned()) + Ok(client_events::PushWasmCode(code_hash.ok_or_else(|| { + IbcEventError::missing_key(client_events::WASM_CODE_HASH_ATTRIBUTE_KEY.to_owned()) })?)) } diff --git a/hyperspace/cosmos/src/provider.rs b/hyperspace/cosmos/src/provider.rs index 9a62ea3b3..24ce59651 100644 --- a/hyperspace/cosmos/src/provider.rs +++ b/hyperspace/cosmos/src/provider.rs @@ -1275,7 +1275,7 @@ where .flat_map(|e| ibc_event_try_from_abci_event(e, height).ok().into_iter()) .filter(|e| matches!(e, IbcEvent::PushWasmCode(_))) .collect::>(); - let code_id = if result.clone().len() != 1 { + let code_hash = if result.clone().len() != 1 { return Err(Error::from(format!( "Expected exactly one PushWasmCode event, found {}", result.len() @@ -1298,7 +1298,7 @@ where // Error::from(format!("Failed to upload wasm code to grpc endpoint: {:?}", e)) // })?; - Ok(code_id) + Ok(code_hash) } } diff --git a/hyperspace/parachain/src/lib.rs b/hyperspace/parachain/src/lib.rs index 5ae222976..417ebe64f 100644 --- a/hyperspace/parachain/src/lib.rs +++ b/hyperspace/parachain/src/lib.rs @@ -186,7 +186,7 @@ pub struct ParachainClientConfig { pub key_type: String, /// All the client states and headers will be wrapped in WASM ones using the WASM code ID. #[serde(default)] - pub wasm_code_id: Option, + pub wasm_code_hash: Option, } impl ParachainClient diff --git a/hyperspace/parachain/src/provider.rs b/hyperspace/parachain/src/provider.rs index 6e957cb4a..c319ddf8d 100644 --- a/hyperspace/parachain/src/provider.rs +++ b/hyperspace/parachain/src/provider.rs @@ -555,8 +555,8 @@ where fetch_timestamp_extrinsic_with_proof(&self.para_client, Some(header.hash())) .await .map_err(Error::BeefyProver)?; - let code_id = if let AnyClientState::Wasm(client_state) = &client_state { - Some(client_state.code_id.clone()) + let code_hash = if let AnyClientState::Wasm(client_state) = &client_state { + Some(client_state.code_hash.clone()) } else { None }; @@ -564,7 +564,7 @@ where header: header.encode(), extrinsic: extrinsic_with_proof.ext, extrinsic_proof: extrinsic_with_proof.proof, - code_id, + code_hash, }; Ok(Some(host_consensus_proof.encode())) } diff --git a/hyperspace/testsuite/tests/parachain_cosmos.rs b/hyperspace/testsuite/tests/parachain_cosmos.rs index 0e409b170..e0629d18e 100644 --- a/hyperspace/testsuite/tests/parachain_cosmos.rs +++ b/hyperspace/testsuite/tests/parachain_cosmos.rs @@ -90,7 +90,7 @@ async fn setup_clients() -> (AnyChain, AnyChain) { finality_protocol: FinalityProtocol::Grandpa, private_key: "//Alice".to_string(), key_type: "sr25519".to_string(), - wasm_code_id: None, + wasm_code_hash: None, }; let mut config_b = CosmosClientConfig { @@ -110,7 +110,7 @@ async fn setup_clients() -> (AnyChain, AnyChain) { mnemonic: "oxygen fall sure lava energy veteran enroll frown question detail include maximum" .to_string(), - wasm_code_id: None, + wasm_code_hash: None, channel_whitelist: vec![], common: CommonClientConfig { skip_optional_client_updates: true, @@ -121,8 +121,8 @@ async fn setup_clients() -> (AnyChain, AnyChain) { let chain_b = CosmosClient::::new(config_b.clone()).await.unwrap(); let wasm_data = tokio::fs::read(&args.wasm_path).await.expect("Failed to read wasm file"); - let code_id = match chain_b.upload_wasm(wasm_data.clone()).await { - Ok(code_id) => code_id, + let code_hash = match chain_b.upload_wasm(wasm_data.clone()).await { + Ok(code_hash) => code_hash, Err(e) => { let e_str = format!("{:?}", e); if !e_str.contains("wasm code already exists") { @@ -131,8 +131,8 @@ async fn setup_clients() -> (AnyChain, AnyChain) { sha2_256(&wasm_data).to_vec() }, }; - let code_id_str = hex::encode(code_id); - config_b.wasm_code_id = Some(code_id_str); + let code_hash_str = hex::encode(code_hash); + config_b.wasm_code_hash = Some(code_hash_str); let mut chain_a_wrapped = AnyConfig::Parachain(config_a).into_client().await.unwrap(); let mut chain_b_wrapped = AnyConfig::Cosmos(config_b).into_client().await.unwrap(); diff --git a/hyperspace/testsuite/tests/parachain_parachain.rs b/hyperspace/testsuite/tests/parachain_parachain.rs index 9375d34d0..75c076982 100644 --- a/hyperspace/testsuite/tests/parachain_parachain.rs +++ b/hyperspace/testsuite/tests/parachain_parachain.rs @@ -73,7 +73,7 @@ async fn setup_clients() -> (ParachainClient, ParachainClient (ParachainClient, ParachainClient::new(config_a).await.unwrap(); diff --git a/ibc/modules/src/core/ics02_client/events.rs b/ibc/modules/src/core/ics02_client/events.rs index 7b11566a9..3eed21021 100644 --- a/ibc/modules/src/core/ics02_client/events.rs +++ b/ibc/modules/src/core/ics02_client/events.rs @@ -35,7 +35,7 @@ pub const CLIENT_TYPE_ATTRIBUTE_KEY: &str = "client_type"; pub const CONSENSUS_HEIGHT_ATTRIBUTE_KEY: &str = "consensus_height"; /// The content of the `key` field for the attribute containing WASM code ID. -pub const WASM_CODE_ID_ATTRIBUTE_KEY: &str = "wasm_code_id"; +pub const WASM_CODE_HASH_ATTRIBUTE_KEY: &str = "wasm_code_hash"; /// NewBlock event signals the committing & execution of a new block. // TODO - find a better place for NewBlock @@ -264,11 +264,11 @@ impl From for IbcEvent { } } -pub type CodeId = Vec; +pub type CodeHash = Vec; /// Signals a recent pushed WASM code to the chain. #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize)] -pub struct PushWasmCode(pub CodeId); +pub struct PushWasmCode(pub CodeHash); impl From for IbcEvent { fn from(v: PushWasmCode) -> Self { diff --git a/ibc/proto/src/prost/ibc.lightclients.wasm.v1.rs b/ibc/proto/src/prost/ibc.lightclients.wasm.v1.rs index 2504bf8f9..615c362c1 100644 --- a/ibc/proto/src/prost/ibc.lightclients.wasm.v1.rs +++ b/ibc/proto/src/prost/ibc.lightclients.wasm.v1.rs @@ -12,7 +12,7 @@ pub struct MsgPushNewWasmCode { #[derive(Clone, PartialEq, ::prost::Message)] pub struct MsgPushNewWasmCodeResponse { #[prost(bytes = "vec", tag = "1")] - pub code_id: ::prost::alloc::vec::Vec, + pub code_hash: ::prost::alloc::vec::Vec, } /// Generated client implementations. #[cfg(feature = "client")] @@ -238,7 +238,7 @@ pub mod msg_server { #[derive(Clone, PartialEq, ::prost::Message)] pub struct WasmCodeQuery { #[prost(string, tag = "1")] - pub code_id: ::prost::alloc::string::String, + pub code_hash: ::prost::alloc::string::String, } /// WasmCode response #[allow(clippy::derive_partial_eq_without_eq)] @@ -475,7 +475,7 @@ pub struct ClientState { #[prost(bytes = "vec", tag = "1")] pub data: ::prost::alloc::vec::Vec, #[prost(bytes = "vec", tag = "2")] - pub code_id: ::prost::alloc::vec::Vec, + pub code_hash: ::prost::alloc::vec::Vec, #[prost(message, optional, tag = "3")] pub latest_height: ::core::option::Option, } diff --git a/light-clients/ics07-tendermint-cw/src/client.rs b/light-clients/ics07-tendermint-cw/src/client.rs index 9850cbcd4..af7b5f185 100644 --- a/light-clients/ics07-tendermint-cw/src/client.rs +++ b/light-clients/ics07-tendermint-cw/src/client.rs @@ -27,7 +27,7 @@ use ibc::{ client_state::ClientType, context::{ClientKeeper, ClientReader, ClientTypes}, error::Error, - events::CodeId, + events::CodeHash, }, ics24_host::identifier::ClientId, }, @@ -190,7 +190,7 @@ impl<'a, H: HostFunctionsProvider + 'static> ClientKeeper for Context<'a, H> { client_state: Self::AnyClientState, ) -> Result<(), Error> { let client_states = ReadonlyClientStates::new(self.storage()); - let code_id = match self.code_id.clone() { + let code_hash = match self.code_hash.clone() { None => { let encoded_wasm_client_state = client_states .get() @@ -207,12 +207,12 @@ impl<'a, H: HostFunctionsProvider + 'static> ClientKeeper for Context<'a, H> { e )) })?; - wasm_client_state.code_id + wasm_client_state.code_hash }, Some(x) => x, }; - let encoded = Self::encode_client_state(client_state, code_id)?; + let encoded = Self::encode_client_state(client_state, code_hash)?; let mut client_state_storage = ClientStates::new(self.storage_mut()); client_state_storage.insert(encoded); Ok(()) @@ -299,7 +299,7 @@ impl<'a, H: Clone> Context<'a, H> { pub fn encode_client_state( client_state: ClientState, - code_id: CodeId, + code_hash: CodeHash, // encoded_wasm_client_state: Vec, ) -> Result, Error> { // let any = Any::decode(&*encoded_wasm_client_state).map_err(Error::decode)?; @@ -315,7 +315,7 @@ impl<'a, H: Clone> Context<'a, H> { // })?; let mut wasm_client_state = ics08_wasm::client_state::ClientState::::default(); - wasm_client_state.code_id = code_id; + wasm_client_state.code_hash = code_hash; wasm_client_state.data = client_state.to_any().encode_to_vec(); wasm_client_state.latest_height = client_state.latest_height().into(); let vec1 = wasm_client_state.to_any().encode_to_vec(); @@ -325,7 +325,6 @@ impl<'a, H: Clone> Context<'a, H> { pub fn encode_consensus_state(consensus_state: ConsensusState) -> Vec { let wasm_consensus_state = ics08_wasm::consensus_state::ConsensusState { data: consensus_state.to_any().encode_to_vec(), - timestamp: consensus_state.timestamp().nanoseconds(), inner: Box::new(FakeInner), }; wasm_consensus_state.to_any().encode_to_vec() diff --git a/light-clients/ics07-tendermint-cw/src/context.rs b/light-clients/ics07-tendermint-cw/src/context.rs index 0003cec09..81a4f76c0 100644 --- a/light-clients/ics07-tendermint-cw/src/context.rs +++ b/light-clients/ics07-tendermint-cw/src/context.rs @@ -23,7 +23,7 @@ use crate::{ use cosmwasm_std::{DepsMut, Env, Storage}; use ibc::{ core::{ - ics02_client::{error::Error, events::CodeId}, + ics02_client::{error::Error, events::CodeHash}, ics24_host::identifier::ClientId, ics26_routing::context::ReaderContext, }, @@ -38,7 +38,7 @@ use std::{fmt, fmt::Debug, marker::PhantomData}; pub struct Context<'a, H> { pub deps: DepsMut<'a>, pub env: Env, - pub code_id: Option, + pub code_hash: Option, _phantom: PhantomData, } @@ -64,7 +64,7 @@ impl<'a, H> Clone for Context<'a, H> { impl<'a, H> Context<'a, H> { pub fn new(deps: DepsMut<'a>, env: Env) -> Self { - Self { deps, _phantom: Default::default(), env, code_id: None } + Self { deps, _phantom: Default::default(), env, code_hash: None } } pub fn log(&self, msg: &str) { @@ -153,7 +153,7 @@ where // let data = client_states.get_prefixed(prefix).ok_or_else(|| { // ContractError::Tendermint("no client state found for prefix".to_string()) // })?; - let code_id = match self.code_id.clone() { + let code_hash = match self.code_hash.clone() { None => { let encoded_wasm_client_state = client_states.get().ok_or_else(|| { ContractError::Tendermint( @@ -177,12 +177,12 @@ where .to_string(), ) })?; - wasm_client_state.code_id + wasm_client_state.code_hash }, Some(x) => x, }; - let encoded = Context::::encode_client_state(client_state, code_id).map_err(|e| { + let encoded = Context::::encode_client_state(client_state, code_hash).map_err(|e| { ContractError::Tendermint(format!("error encoding client state: {:?}", e)) })?; let mut client_states = ClientStates::new(self.storage_mut()); diff --git a/light-clients/ics07-tendermint-cw/src/contract.rs b/light-clients/ics07-tendermint-cw/src/contract.rs index 53590d83e..aa541f393 100644 --- a/light-clients/ics07-tendermint-cw/src/contract.rs +++ b/light-clients/ics07-tendermint-cw/src/contract.rs @@ -136,7 +136,7 @@ fn process_instantiate_msg( let any = Any::decode(&mut msg.consensus_state.data.as_slice())?; let consensus_state = ConsensusState::decode_vec(&any.value)?; - ctx.code_id = Some(msg.client_state.code_id); + ctx.code_hash = Some(msg.client_state.code_hash); let height = client_state.latest_height(); ctx.store_client_state(client_id.clone(), client_state) .map_err(|e| ContractError::Tendermint(e.to_string()))?; diff --git a/light-clients/ics08-wasm/src/client_def.rs b/light-clients/ics08-wasm/src/client_def.rs index bb2bd837f..e687273f1 100644 --- a/light-clients/ics08-wasm/src/client_def.rs +++ b/light-clients/ics08-wasm/src/client_def.rs @@ -100,7 +100,7 @@ where )?; let client_state = ClientState { data: client_state.data.clone(), - code_id: client_state.code_id.clone(), + code_hash: client_state.code_hash.clone(), inner: Box::new(inner_client_state), latest_height: client_state.latest_height, _phantom: PhantomData, @@ -118,7 +118,7 @@ where .update_state_on_misbehaviour(*client_state.inner, client_msg.into_inner())?; Ok(ClientState { data: client_state.data.clone(), - code_id: client_state.code_id.clone(), + code_hash: client_state.code_hash.clone(), inner: Box::new(inner_client_state), latest_height: client_state.latest_height, _phantom: PhantomData, @@ -165,7 +165,7 @@ where ClientState { inner: Box::new(client_state), data: old_client_state.data.clone(), - code_id: old_client_state.code_id.clone(), + code_hash: old_client_state.code_hash.clone(), latest_height: old_client_state.latest_height.clone(), _phantom: Default::default(), }, @@ -192,7 +192,7 @@ where )?; let client_state = ClientState { data: old_client_state.data.clone(), - code_id: old_client_state.code_id.clone(), + code_hash: old_client_state.code_hash.clone(), inner: Box::new(inner_client_state), latest_height: old_client_state.latest_height, _phantom: PhantomData, diff --git a/light-clients/ics08-wasm/src/client_state.rs b/light-clients/ics08-wasm/src/client_state.rs index d9074ae33..be5ee9d75 100644 --- a/light-clients/ics08-wasm/src/client_state.rs +++ b/light-clients/ics08-wasm/src/client_state.rs @@ -55,7 +55,7 @@ pub struct ClientState { pub data: Bytes, #[cfg_attr(feature = "cosmwasm", schemars(with = "String"))] #[cfg_attr(feature = "cosmwasm", serde(with = "Base64", default))] - pub code_id: Bytes, + pub code_hash: Bytes, pub latest_height: Height, #[cfg_attr(feature = "cosmwasm", serde(skip))] #[cfg_attr(feature = "cosmwasm", schemars(skip))] @@ -166,7 +166,7 @@ where let inner = AnyClientState::try_from(any).map_err(|e| e.to_string())?; Ok(Self { data: raw.data, - code_id: raw.code_id, + code_hash: raw.code_hash, inner: Box::new(inner), latest_height: raw .latest_height @@ -186,7 +186,7 @@ where fn from(client_state: ClientState) -> Self { Self { data: client_state.data, - code_id: client_state.code_id, + code_hash: client_state.code_hash, latest_height: Some(client_state.latest_height.into()), } } @@ -209,7 +209,7 @@ impl Default fn default() -> Self { ClientState { data: vec![], - code_id: vec![], + code_hash: vec![], latest_height: Default::default(), inner: Box::new(AnyClientState::default()), _phantom: Default::default(), diff --git a/light-clients/ics08-wasm/src/consensus_state.rs b/light-clients/ics08-wasm/src/consensus_state.rs index 9f710e411..4da5b79c4 100644 --- a/light-clients/ics08-wasm/src/consensus_state.rs +++ b/light-clients/ics08-wasm/src/consensus_state.rs @@ -70,7 +70,7 @@ where } fn timestamp(&self) -> Timestamp { - self.inner.timestamp() + unimplemented!() } fn encode_to_vec(&self) -> Result, tendermint_proto::Error> { @@ -128,6 +128,6 @@ where impl Default for ConsensusState { fn default() -> Self { - ConsensusState { data: vec![], timestamp: 0, inner: Box::new(AnyConsensusState::default()) } + ConsensusState { data: vec![], inner: Box::new(AnyConsensusState::default()) } } } diff --git a/light-clients/ics10-grandpa-cw/src/client.rs b/light-clients/ics10-grandpa-cw/src/client.rs index ee35189bb..5c058a44a 100644 --- a/light-clients/ics10-grandpa-cw/src/client.rs +++ b/light-clients/ics10-grandpa-cw/src/client.rs @@ -30,7 +30,7 @@ use ibc::{ client_state::ClientType, context::{ClientKeeper, ClientReader, ClientTypes}, error::Error, - events::CodeId, + events::CodeHash, }, ics24_host::identifier::ClientId, }, @@ -201,7 +201,7 @@ impl<'a, H: HostFunctions
> ClientKeeper for Context<' let client_states = ReadonlyClientStates::new(self.storage()); // let data = client_states.get().ok_or_else(|| // Error::client_not_found(client_id.clone()))?; - let code_id = match self.code_id.clone() { + let code_hash = match self.code_hash.clone() { None => { let encoded_wasm_client_state = client_states .get() @@ -218,12 +218,12 @@ impl<'a, H: HostFunctions
> ClientKeeper for Context<' e )) })?; - wasm_client_state.code_id + wasm_client_state.code_hash }, Some(x) => x, }; - let vec1 = Self::encode_client_state(client_state, code_id)?; + let vec1 = Self::encode_client_state(client_state, code_hash)?; log!(self, "in cliden : [store_client_state] >> wasm client state (raw)"); let mut client_state_storage = ClientStates::new(self.storage_mut()); client_state_storage.insert(vec1); @@ -313,7 +313,7 @@ impl<'a, H: Clone> Context<'a, H> { pub fn encode_client_state( client_state: ClientState, - code_id: CodeId, + code_hash: CodeHash, // encoded_wasm_client_state: Vec, ) -> Result, Error> { // let any = Any::decode(&*encoded_wasm_client_state).map_err(Error::decode)?; @@ -329,7 +329,7 @@ impl<'a, H: Clone> Context<'a, H> { // })?; let mut wasm_client_state = ics08_wasm::client_state::ClientState::::default(); - wasm_client_state.code_id = code_id; + wasm_client_state.code_hash = code_hash; wasm_client_state.data = client_state.to_any().encode_to_vec(); wasm_client_state.latest_height = client_state.latest_height().into(); let vec1 = wasm_client_state.to_any().encode_to_vec(); diff --git a/light-clients/ics10-grandpa-cw/src/context.rs b/light-clients/ics10-grandpa-cw/src/context.rs index 48a068ade..d24db38a7 100644 --- a/light-clients/ics10-grandpa-cw/src/context.rs +++ b/light-clients/ics10-grandpa-cw/src/context.rs @@ -27,7 +27,7 @@ use cosmwasm_std::{DepsMut, Env, Storage}; use grandpa_light_client_primitives::HostFunctions; use ibc::{ core::{ - ics02_client::{error::Error, events::CodeId}, + ics02_client::{error::Error, events::CodeHash}, ics24_host::identifier::ClientId, ics26_routing::context::ReaderContext, }, @@ -43,7 +43,7 @@ use std::{fmt, fmt::Debug, marker::PhantomData}; pub struct Context<'a, H> { pub deps: DepsMut<'a>, pub env: Env, - pub code_id: Option, + pub code_hash: Option, _phantom: PhantomData, } @@ -69,7 +69,7 @@ impl<'a, H> Clone for Context<'a, H> { impl<'a, H> Context<'a, H> { pub fn new(deps: DepsMut<'a>, env: Env) -> Self { - Self { deps, _phantom: Default::default(), env, code_id: None } + Self { deps, _phantom: Default::default(), env, code_hash: None } } pub fn log(&self, msg: &str) { @@ -170,7 +170,7 @@ where // let data = client_states.get_prefixed(prefix).ok_or_else(|| { // ContractError::Tendermint("no client state found for prefix".to_string()) // })?; - let code_id = match self.code_id.clone() { + let code_hash = match self.code_hash.clone() { None => { let encoded_wasm_client_state = client_states.get().ok_or_else(|| { ContractError::Grandpa( @@ -194,11 +194,11 @@ where .to_string(), ) })?; - wasm_client_state.code_id + wasm_client_state.code_hash }, Some(x) => x, }; - let encoded = Context::::encode_client_state(client_state, code_id) + let encoded = Context::::encode_client_state(client_state, code_hash) .map_err(|e| ContractError::Grandpa(format!("error encoding client state: {:?}", e)))?; let mut client_states = ClientStates::new(self.storage_mut()); client_states.insert_prefixed(encoded, prefix); diff --git a/light-clients/ics10-grandpa-cw/src/contract.rs b/light-clients/ics10-grandpa-cw/src/contract.rs index cf753ad72..ea722b876 100644 --- a/light-clients/ics10-grandpa-cw/src/contract.rs +++ b/light-clients/ics10-grandpa-cw/src/contract.rs @@ -128,7 +128,7 @@ fn process_instantiate_msg( let consensus_state = ConsensusState::decode_vec(&any.value)?; let height = client_state.latest_height(); - ctx.code_id = Some(msg.client_state.code_id); + ctx.code_hash = Some(msg.client_state.code_hash); ctx.store_client_state(client_id.clone(), client_state) .map_err(|e| ContractError::Grandpa(e.to_string()))?; ctx.store_consensus_state(client_id, height, consensus_state) From d3e49b4de065edcc57b2a41d42faa0cbcd760c1f Mon Sep 17 00:00:00 2001 From: Steve Miskovetz Date: Mon, 7 Aug 2023 10:16:12 -0600 Subject: [PATCH 04/37] Make executes -> sudo, move some execute msgs to query, add read-only context for queries, and add TimestampAtHeight query. --- .../ics07-tendermint-cw/src/channel.rs | 114 +++++++- .../ics07-tendermint-cw/src/client.rs | 252 ++++++++++++++++++ .../ics07-tendermint-cw/src/connection.rs | 32 ++- .../src/context_read_only.rs | 196 ++++++++++++++ .../ics07-tendermint-cw/src/contract.rs | 170 ++++++------ .../ics07-tendermint-cw/src/error.rs | 6 + .../ics07-tendermint-cw/src/helpers.rs | 7 +- light-clients/ics07-tendermint-cw/src/lib.rs | 1 + light-clients/ics07-tendermint-cw/src/msg.rs | 60 +++-- 9 files changed, 735 insertions(+), 103 deletions(-) create mode 100644 light-clients/ics07-tendermint-cw/src/context_read_only.rs diff --git a/light-clients/ics07-tendermint-cw/src/channel.rs b/light-clients/ics07-tendermint-cw/src/channel.rs index c48535bde..a3aa5ba95 100644 --- a/light-clients/ics07-tendermint-cw/src/channel.rs +++ b/light-clients/ics07-tendermint-cw/src/channel.rs @@ -13,7 +13,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::context::Context; +use crate::{ + context::Context, + context_read_only::ContextReadOnly, +}; use ibc::{ core::{ ics04_channel::{ @@ -139,3 +142,112 @@ impl<'a, H: HostFunctionsProvider> ChannelReader for Context<'a, H> { unimplemented!("'max_expected_time_per_block' is unavailable from the client") } } + + +impl<'a, H: HostFunctionsProvider> ChannelReader for ContextReadOnly<'a, H> { + fn channel_end(&self, _port_channel_id: &(PortId, ChannelId)) -> Result { + Err(Error::implementation_specific( + "'channel_end' is unavailable from the client".to_string(), + )) + } + + fn connection_channels( + &self, + _conn_id: &ConnectionId, + ) -> Result, Error> { + Err(Error::implementation_specific( + "'connection_channels' is unavailable from the client".to_string(), + )) + } + + fn get_next_sequence_send( + &self, + _port_channel_id: &(PortId, ChannelId), + ) -> Result { + Err(Error::implementation_specific( + "'get_next_sequence_send' is unavailable from the client".to_string(), + )) + } + + fn get_next_sequence_recv( + &self, + _port_channel_id: &(PortId, ChannelId), + ) -> Result { + Err(Error::implementation_specific( + "'get_next_sequence_recv' is unavailable from the client".to_string(), + )) + } + + fn get_next_sequence_ack( + &self, + _port_channel_id: &(PortId, ChannelId), + ) -> Result { + Err(Error::implementation_specific( + "'get_next_sequence_ack' is unavailable from the client".to_string(), + )) + } + + fn get_packet_commitment( + &self, + _key: &(PortId, ChannelId, Sequence), + ) -> Result { + Err(Error::implementation_specific( + "'get_packet_commitment' is unavailable from the client".to_string(), + )) + } + + fn get_packet_receipt(&self, _key: &(PortId, ChannelId, Sequence)) -> Result { + Err(Error::implementation_specific( + "'get_packet_receipt' is unavailable from the client".to_string(), + )) + } + + fn get_packet_acknowledgement( + &self, + _key: &(PortId, ChannelId, Sequence), + ) -> Result { + Err(Error::implementation_specific( + "'get_packet_acknowledgement' is unavailable from the client".to_string(), + )) + } + + /// A hashing function for packet commitments + fn hash(&self, value: Vec) -> Vec { + let mut hasher = Sha256::default(); + hasher.update(value); + hasher.finalize().to_vec() + } + + fn client_update_time( + &self, + _client_id: &ClientId, + _height: Height, + ) -> Result { + Err(Error::implementation_specific( + "'client_update_time' is unavailable from the client".to_string(), + )) + } + + fn client_update_height( + &self, + _client_id: &ClientId, + _height: Height, + ) -> Result { + Err(Error::implementation_specific( + "'client_update_height' is unavailable from the client".to_string(), + )) + } + + /// Returns a counter on the number of channel ids have been created thus far. + /// The value of this counter should increase only via method + /// `ChannelKeeper::increase_channel_counter`. + fn channel_counter(&self) -> Result { + Err(Error::implementation_specific( + "'channel_counter' is unavailable from the client".to_string(), + )) + } + + fn max_expected_time_per_block(&self) -> Duration { + unimplemented!("'max_expected_time_per_block' is unavailable from the client") + } +} \ No newline at end of file diff --git a/light-clients/ics07-tendermint-cw/src/client.rs b/light-clients/ics07-tendermint-cw/src/client.rs index af7b5f185..a74238284 100644 --- a/light-clients/ics07-tendermint-cw/src/client.rs +++ b/light-clients/ics07-tendermint-cw/src/client.rs @@ -14,6 +14,7 @@ // limitations under the License. use crate::{ + context_read_only::ContextReadOnly, context::Context, ics23::{ ClientStates, ConsensusStates, FakeInner, ProcessedStates, ReadonlyClientStates, @@ -330,3 +331,254 @@ impl<'a, H: Clone> Context<'a, H> { wasm_consensus_state.to_any().encode_to_vec() } } + +/////////////////////////////////////////////////////////////////////////////////// + +impl<'a, H: HostFunctionsProvider + 'static> ClientTypes for ContextReadOnly<'a, H> { + type AnyClientMessage = ClientMessage; + type AnyClientState = ClientState; + type AnyConsensusState = ConsensusState; + type ClientDef = TendermintClient; +} + +impl<'a, H: HostFunctionsProvider + 'static> ClientReader for ContextReadOnly<'a, H> { + fn client_type(&self, client_id: &ClientId) -> Result { + let clients = ReadonlyClients::new(self.storage()); + if !clients.contains_key(client_id) { + return Err(Error::client_not_found(client_id.clone())) + } + + let data = clients + .get(client_id) + .ok_or_else(|| Error::client_not_found(client_id.clone()))?; + let data = String::from_utf8(data).map_err(|e| { + Error::implementation_specific(format!( + "[client_type]: error decoding client type bytes to string {}", + e + )) + })?; + match ClientType::from_str(&data) { + Err(_err) => Err(Error::unknown_client_type(data.to_string())), + Ok(val) => Ok(val), + } + } + + fn client_state(&self, client_id: &ClientId) -> Result, Error> { + let client_states = ReadonlyClientStates::new(self.storage()); + let data = client_states.get().ok_or_else(|| Error::client_not_found(client_id.clone()))?; + let state = Self::decode_client_state(&data)?; + Ok(state) + } + + fn consensus_state( + &self, + client_id: &ClientId, + height: Height, + ) -> Result { + let consensus_states = ReadonlyConsensusStates::new(self.storage()); + let value = consensus_states + .get(height) + .ok_or_else(|| Error::consensus_state_not_found(client_id.clone(), height))?; + let any_consensus_state = Self::decode_consensus_state(&value)?; + Ok(any_consensus_state) + } + + fn host_client_type(&self) -> String { + "ics07-tendermint".to_string() + } + + /// Similar to `consensus_state`, attempt to retrieve the consensus state, + /// but return `None` if no state exists at the given height. + /*fn maybe_consensus_state( + &self, + client_id: &ClientId, + height: Height, + ) -> Result, Error> { + unimplemented!() + //match self.consensus_state(client_id, height, &mut Vec::new()) { + // Ok(cs) => Ok(Some(cs)), + // Err(e) => match e.detail() { + // ErrorDetail::ConsensusStateNotFound(_) => Ok(None), + // _ => Err(e), + // }, + //} + }*/ + + fn next_consensus_state( + &self, + client_id: &ClientId, + height: Height, + ) -> Result, Error> { + let processed_state = ReadonlyProcessedStates::new(self.storage()); + match processed_state.get_next_height(height) { + Some(next_height) => self + .consensus_state(&client_id.clone(), next_height) + .and_then(|cs| Ok(Some(cs))), + None => Ok(None), + } + } + + fn prev_consensus_state( + &self, + client_id: &ClientId, + height: Height, + ) -> Result, Error> { + let processed_state = ReadonlyProcessedStates::new(self.storage()); + match processed_state.get_prev_height(height) { + Some(prev_height) => self + .consensus_state(&client_id.clone(), prev_height) + .and_then(|cs| Ok(Some(cs))), + None => Ok(None), + } + } + + fn host_height(&self) -> Height { + Height::new(0, self.env.block.height) + } + + fn host_timestamp(&self) -> Timestamp { + let time = self.env.block.time; + Timestamp::from_nanoseconds(time.nanos()).expect("invalid timestamp") + } + + fn host_consensus_state( + &self, + _height: Height, + _proof: Option>, + _client_state: &ClientState, + ) -> Result { + unimplemented!() + /*let consensus_state = + HOST_CONSENSUS_STATE.load(self.storage(), height.revision_height).map_err(|_| { + Error::implementation_specific(format!( + "[host_consensus_state]: consensus state not found for host at height {}", + height + )) + })?; + Ok(consensus_state)*/ + } + + fn client_counter(&self) -> Result { + unimplemented!() + /*let count = CLIENT_COUNTER.load(self.storage()).unwrap_or_default(); + log!(self, "in client : [client_counter] >> client_counter: {:?}", count); + Ok(count as u64)*/ + } +} + +impl<'a, H: HostFunctionsProvider + 'static> ClientKeeper for ContextReadOnly<'a, H> { + fn store_client_type( + &mut self, + _client_id: ClientId, + _client_type: ClientType, + ) -> Result<(), Error> { + unimplemented!() + } + + fn store_client_state( + &mut self, + client_id: ClientId, + client_state: Self::AnyClientState, + ) -> Result<(), Error> { + unimplemented!() + } + + fn store_consensus_state( + &mut self, + client_id: ClientId, + height: Height, + consensus_state: Self::AnyConsensusState, + ) -> Result<(), Error> { + unimplemented!() + } + + fn increase_client_counter(&mut self) { + unimplemented!() + } + + fn store_update_time( + &mut self, + _client_id: ClientId, + height: Height, + timestamp: Timestamp, + ) -> Result<(), Error> { + unimplemented!() + } + + fn store_update_height( + &mut self, + _client_id: ClientId, + height: Height, + host_height: Height, + ) -> Result<(), Error> { + unimplemented!() + } + + fn validate_self_client(&self, _client_state: &Self::AnyClientState) -> Result<(), Error> { + unimplemented!() + } +} + +impl<'a, H: Clone> ContextReadOnly<'a, H> { + pub fn decode_client_state(data: &[u8]) -> Result, Error> { + let any = Any::decode(data).map_err(Error::decode)?; + let wasm_state = + ics08_wasm::client_state::ClientState::::decode_vec( + &any.value, + ) + .map_err(|e| { + Error::implementation_specific(format!( + "[client_state]: error decoding client state bytes to WasmConsensusState {}", + e + )) + })?; + let any = Any::decode(&*wasm_state.data).map_err(|e| Error::decode(e))?; + let state = + ClientState::::decode_vec(&*any.value).map_err(Error::invalid_any_client_state)?; + Ok(state) + } + + pub fn decode_consensus_state(value: &[u8]) -> Result { + let any = Any::decode(&mut &*value).map_err(Error::decode)?; + let wasm_consensus_state = + ics08_wasm::consensus_state::ConsensusState::::decode_vec(&*any.value) + .map_err(Error::invalid_any_consensus_state)?; + let any = Any::decode(&mut &wasm_consensus_state.data[..]).map_err(Error::decode)?; + let any_consensus_state = + ConsensusState::decode_vec(&*any.value).map_err(Error::invalid_any_consensus_state)?; + Ok(any_consensus_state) + } + + pub fn encode_client_state( + client_state: ClientState, + code_hash: CodeHash, + // encoded_wasm_client_state: Vec, + ) -> Result, Error> { + // let any = Any::decode(&*encoded_wasm_client_state).map_err(Error::decode)?; + // let mut wasm_client_state = + // ics08_wasm::client_state::ClientState::::decode_vec( + // &any.value, + // ) + // .map_err(|e| { + // Error::implementation_specific(format!( + // "[client_state]: error decoding client state bytes to WasmConsensusState {}", + // e + // )) + // })?; + let mut wasm_client_state = + ics08_wasm::client_state::ClientState::::default(); + wasm_client_state.code_hash = code_hash; + wasm_client_state.data = client_state.to_any().encode_to_vec(); + wasm_client_state.latest_height = client_state.latest_height().into(); + let vec1 = wasm_client_state.to_any().encode_to_vec(); + Ok(vec1) + } + + pub fn encode_consensus_state(consensus_state: ConsensusState) -> Vec { + let wasm_consensus_state = ics08_wasm::consensus_state::ConsensusState { + data: consensus_state.to_any().encode_to_vec(), + inner: Box::new(FakeInner), + }; + wasm_consensus_state.to_any().encode_to_vec() + } +} diff --git a/light-clients/ics07-tendermint-cw/src/connection.rs b/light-clients/ics07-tendermint-cw/src/connection.rs index e29b82173..aeb6194cb 100644 --- a/light-clients/ics07-tendermint-cw/src/connection.rs +++ b/light-clients/ics07-tendermint-cw/src/connection.rs @@ -13,7 +13,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::context::Context; +use crate::{ + context_read_only::ContextReadOnly, + context::Context, +}; use ibc::{ core::{ ics03_connection::{connection::ConnectionEnd, context::ConnectionReader, error::Error}, @@ -51,3 +54,30 @@ impl<'a, H: HostFunctionsProvider> ConnectionReader for Context<'a, H> { )) } } + +impl<'a, H: HostFunctionsProvider> ConnectionReader for ContextReadOnly<'a, H> { + fn minimum_delay_period(&self) -> Duration { + unimplemented!("minimum_delay_period") + } + + fn connection_end(&self, _conn_id: &ConnectionId) -> Result { + Err(Error::implementation_specific( + "'connection_end' is unavailable from the client".to_string(), + )) + } + + fn host_oldest_height(&self) -> Height { + unimplemented!("the method should be removed in the future"); + } + + #[allow(clippy::disallowed_methods)] + fn commitment_prefix(&self) -> CommitmentPrefix { + unimplemented!("'commitment_prefix' is unavailable from the client"); + } + + fn connection_counter(&self) -> Result { + Err(Error::implementation_specific( + "'connection_counter' is unavailable from the client".to_string(), + )) + } +} \ No newline at end of file diff --git a/light-clients/ics07-tendermint-cw/src/context_read_only.rs b/light-clients/ics07-tendermint-cw/src/context_read_only.rs new file mode 100644 index 000000000..011fd7ba3 --- /dev/null +++ b/light-clients/ics07-tendermint-cw/src/context_read_only.rs @@ -0,0 +1,196 @@ +// Copyright (C) 2022 ComposableFi. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::{ + ics23::{ + ClientStates, ConsensusStates, FakeInner, ReadonlyClientStates, ReadonlyConsensusStates, + ReadonlyProcessedStates, + }, + ContractError, +}; +use cosmwasm_std::{Deps, Env, Storage}; +use ibc::{ + core::{ + ics02_client::{error::Error, events::CodeHash}, + ics24_host::identifier::ClientId, + ics26_routing::context::ReaderContext, + }, + Height, +}; +use ibc_proto::google::protobuf::Any; +use ics07_tendermint::{ + client_state::ClientState, consensus_state::ConsensusState, HostFunctionsProvider, +}; +use std::{fmt, fmt::Debug, marker::PhantomData}; + +pub struct ContextReadOnly<'a, H> { + pub deps: Deps<'a>, + pub env: Env, + pub code_hash: Option, + _phantom: PhantomData, +} + +impl<'a, H> PartialEq for ContextReadOnly<'a, H> { + fn eq(&self, _other: &Self) -> bool { + true + } +} + +impl<'a, H> Eq for ContextReadOnly<'a, H> {} + +impl<'a, H> Debug for ContextReadOnly<'a, H> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "ContextReadOnly {{ deps: DepsMut }}") + } +} + +impl<'a, H> Clone for ContextReadOnly<'a, H> { + fn clone(&self) -> Self { + panic!("ContextReadOnly is not cloneable") + } +} + +impl<'a, H> ContextReadOnly<'a, H> { + pub fn new(deps: Deps<'a>, env: Env) -> Self { + Self { deps, _phantom: Default::default(), env, code_hash: None } + } + + //pub fn log(&self, msg: &str) { + // self.deps.api.debug(msg) + //} + + pub fn storage(&self) -> &dyn Storage { + self.deps.storage + } + + //pub fn storage_mut(&mut self) -> &mut dyn Storage { + // self.deps.storage + //} +} + +impl<'a, H> ContextReadOnly<'a, H> +where + H: Clone, +{ + pub fn processed_timestamp(&self, height: Height) -> Result { + let processed_state = ReadonlyProcessedStates::new(self.storage()); + match processed_state.get_processed_time(height, &mut Vec::new()) { + Some(time) => Ok(time), + None => ibc::prelude::Err(Error::implementation_specific(format!( + "problem getting processed timestamp" + ))), + } + } + + pub fn processed_height(&self, height: Height) -> Result { + let processed_state = ReadonlyProcessedStates::new(self.storage()); + match processed_state.get_processed_height(height, &mut Vec::new()) { + Some(p_height) => Ok(p_height), + None => ibc::prelude::Err(Error::implementation_specific(format!( + "problem getting processed height" + ))), + } + } + + pub fn consensus_state_prefixed( + &self, + height: Height, + prefix: &[u8], + ) -> Result { + let bytes = ReadonlyConsensusStates::new(self.storage()) + .get_prefixed(height, prefix) + .ok_or_else(|| { + ContractError::Tendermint(format!( + "no consensus state found for height {} and prefix {:?}", + height, prefix, + )) + })?; + ContextReadOnly::::decode_consensus_state(&bytes).map_err(|e| { + ContractError::Tendermint(format!("error decoding consensus state: {:?}", e)) + }) + } +} + +/* pub fn store_consensus_state_prefixed( + &mut self, + height: Height, + consensus_state: ConsensusState, + prefix: &[u8], + ) { + let encoded = Context::::encode_consensus_state(consensus_state); + let mut consensus_states = ConsensusStates::new(self.storage_mut()); + consensus_states.insert_prefixed(height, encoded, prefix); + } + + pub fn client_state_prefixed(&self, prefix: &[u8]) -> Result, ContractError> { + let bytes = + ReadonlyClientStates::new(self.storage()).get_prefixed(prefix).ok_or_else(|| { + ContractError::Tendermint(format!("no client state found for prefix {:?}", prefix,)) + })?; + Context::decode_client_state(&bytes) + .map_err(|e| ContractError::Tendermint(format!("error decoding client state: {:?}", e))) + } + + pub fn store_client_state_prefixed( + &mut self, + client_state: ClientState, + prefix: &[u8], + ) -> Result<(), ContractError> { + use prost::Message; + use tendermint_proto::Protobuf; + let client_states = ReadonlyClientStates::new(self.storage()); + // let data = client_states.get_prefixed(prefix).ok_or_else(|| { + // ContractError::Tendermint("no client state found for prefix".to_string()) + // })?; + let code_hash = match self.code_hash.clone() { + None => { + let encoded_wasm_client_state = client_states.get().ok_or_else(|| { + ContractError::Tendermint( + Error::client_not_found(ClientId::new("x", 1).unwrap()).to_string(), + ) + })?; + let any = Any::decode(&*encoded_wasm_client_state) + .map_err(Error::decode) + .map_err(|e| ContractError::Tendermint(e.to_string()))?; + let wasm_client_state = ics08_wasm::client_state::ClientState::< + FakeInner, + FakeInner, + FakeInner, + >::decode_vec(&any.value) + .map_err(|e| { + ContractError::Tendermint( + Error::implementation_specific(format!( + "[client_state]: error decoding client state bytes to WasmConsensusState {}", + e + )) + .to_string(), + ) + })?; + wasm_client_state.code_hash + }, + Some(x) => x, + }; + + let encoded = Context::::encode_client_state(client_state, code_hash).map_err(|e| { + ContractError::Tendermint(format!("error encoding client state: {:?}", e)) + })?; + let mut client_states = ClientStates::new(self.storage_mut()); + client_states.insert_prefixed(encoded, prefix); + Ok(()) + } +}*/ + +impl<'a, H: HostFunctionsProvider + 'static> ReaderContext for ContextReadOnly<'a, H> {} + diff --git a/light-clients/ics07-tendermint-cw/src/contract.rs b/light-clients/ics07-tendermint-cw/src/contract.rs index aa541f393..7d99a255f 100644 --- a/light-clients/ics07-tendermint-cw/src/contract.rs +++ b/light-clients/ics07-tendermint-cw/src/contract.rs @@ -15,6 +15,7 @@ use crate::{ context::Context, + context_read_only::ContextReadOnly, error::ContractError, helpers::{ check_substitute_and_update_state, prune_oldest_consensus_state, verify_delay_passed, @@ -22,8 +23,8 @@ use crate::{ }, ics23::{FakeInner, ReadonlyProcessedStates}, msg::{ - CheckForMisbehaviourMsg, ContractResult, ExecuteMsg, ExportMetadataMsg, QueryMsg, - QueryResponse, StatusMsg, UpdateStateMsg, UpdateStateOnMisbehaviourMsg, + CheckForMisbehaviourMsg, ContractResult, ExportMetadataMsg, QueryMsg, + QueryResponse, StatusMsg, SudoMsg, UpdateStateMsg, UpdateStateOnMisbehaviourMsg, VerifyClientMessage, VerifyMembershipMsg, VerifyNonMembershipMsg, VerifyUpgradeAndUpdateStateMsg, }, @@ -165,13 +166,11 @@ pub fn instantiate( response.data = Some(data); Ok(response) } - #[cfg_attr(not(feature = "library"), entry_point)] -pub fn execute( +pub fn sudo( deps: DepsMut, env: Env, - _info: MessageInfo, - msg: ExecuteMsg, + msg: SudoMsg, ) -> Result { let client = TendermintClient::::default(); let mut ctx = Context::::new(deps, env); @@ -183,76 +182,14 @@ pub fn execute( } fn process_message( - msg: ExecuteMsg, + msg: SudoMsg, client: TendermintClient, ctx: &mut Context, client_id: ClientId, ) -> Result { //log!(ctx, "process_message: {:?}", msg); let result = match msg { - ExecuteMsg::VerifyMembership(msg) => { - let client_state = ctx - .client_state(&client_id) - .map_err(|e| ContractError::Tendermint(e.to_string()))?; - let msg = VerifyMembershipMsg::try_from(msg)?; - verify_delay_passed(ctx, msg.height, msg.delay_time_period, msg.delay_block_period) - .map_err(|e| ContractError::Tendermint(e.to_string()))?; - let consensus_state = ctx - .consensus_state(&client_id, msg.height) - .map_err(|e| ContractError::Tendermint(e.to_string()))?; - verify_membership::( - &client_state, - &msg.prefix, - &msg.proof, - &consensus_state.root, - msg.path, - msg.value, - ) - .map_err(|e| ContractError::Tendermint(e.to_string()))?; - Ok(()).map(|_| to_binary(&ContractResult::success())) - }, - ExecuteMsg::VerifyNonMembership(msg) => { - let client_state = ctx - .client_state(&client_id) - .map_err(|e| ContractError::Tendermint(e.to_string()))?; - let msg = VerifyNonMembershipMsg::try_from(msg)?; - verify_delay_passed(ctx, msg.height, msg.delay_time_period, msg.delay_block_period) - .map_err(|e| ContractError::Tendermint(e.to_string()))?; - let consensus_state = ctx - .consensus_state(&client_id, msg.height) - .map_err(|e| ContractError::Tendermint(e.to_string()))?; - - verify_non_membership::( - &client_state, - &msg.prefix, - &msg.proof, - &consensus_state.root, - msg.path, - ) - .map_err(|e| ContractError::Tendermint(e.to_string())) - .map(|_| to_binary(&ContractResult::success())) - }, - ExecuteMsg::VerifyClientMessage(msg) => { - let client_state = ctx - .client_state(&client_id) - .map_err(|e| ContractError::Tendermint(e.to_string()))?; - let msg = VerifyClientMessage::try_from(msg)?; - client - .verify_client_message(ctx, client_id, client_state, msg.client_message) - .map_err(|e| ContractError::Tendermint(format!("{e:?}"))) - .map(|_| to_binary(&ContractResult::success())) - }, - ExecuteMsg::CheckForMisbehaviour(msg) => { - let client_state = ctx - .client_state(&client_id) - .map_err(|e| ContractError::Tendermint(e.to_string()))?; - let msg = CheckForMisbehaviourMsg::try_from(msg)?; - client - .check_for_misbehaviour(ctx, client_id, client_state, msg.client_message) - .map_err(|e| ContractError::Tendermint(e.to_string())) - .map(|result| to_binary(&ContractResult::success().misbehaviour(result))) - }, - ExecuteMsg::UpdateStateOnMisbehaviour(msg_raw) => { + SudoMsg::UpdateStateOnMisbehaviour(msg_raw) => { let client_state = ctx .client_state(&client_id) .map_err(|e| ContractError::Tendermint(e.to_string()))?; @@ -266,7 +203,7 @@ fn process_message( Ok(to_binary(&ContractResult::success())) }) }, - ExecuteMsg::UpdateState(msg_raw) => { + SudoMsg::UpdateState(msg_raw) => { let client_state = ctx .client_state(&client_id) .map_err(|e| ContractError::Tendermint(e.to_string()))?; @@ -296,7 +233,7 @@ fn process_message( Ok(to_binary(&ContractResult::success())) }) }, - ExecuteMsg::CheckSubstituteAndUpdateState(_msg) => + SudoMsg::CheckSubstituteAndUpdateState(_msg) => check_substitute_and_update_state::(ctx) .map_err(|e| ContractError::Tendermint(e.to_string())) .and_then(|(cs, cu)| { @@ -306,7 +243,7 @@ fn process_message( .map_err(|e| ContractError::Tendermint(e.to_string()))?; Ok(to_binary(&ContractResult::success())) }), - ExecuteMsg::VerifyUpgradeAndUpdateState(msg) => { + SudoMsg::VerifyUpgradeAndUpdateState(msg) => { let old_client_state = ctx .client_state(&client_id.clone()) .map_err(|e| ContractError::Tendermint(e.to_string()))?; @@ -340,20 +277,32 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { let client_id = ClientId::from_str("08-wasm-0").expect("client id is valid"); //deps.api.debug("In query"); match msg { + QueryMsg::CheckForMisbehaviour(msg) => { + let ctx = ContextReadOnly::::new(deps, env); + let client = TendermintClient::::default(); + let client_state = ctx + .client_state(&client_id) + .map_err(|e| ContractError::Tendermint(e.to_string()))?; + let msg = CheckForMisbehaviourMsg::try_from(msg)?; + client + .check_for_misbehaviour(&ctx, client_id, client_state, msg.client_message) + .map_err(|e| ContractError::Tendermint(e.to_string())) + .map(|result| to_binary(&QueryResponse::success().misbehaviour(result)))? + }, QueryMsg::ClientTypeMsg(_) => unimplemented!("ClientTypeMsg"), QueryMsg::GetLatestHeightsMsg(_) => unimplemented!("GetLatestHeightsMsg"), QueryMsg::ExportMetadata(ExportMetadataMsg {}) => { let ro_proceeded_state = ReadonlyProcessedStates::new(deps.storage); - to_binary(&QueryResponse::genesis_metadata(ro_proceeded_state.get_metadata())) + to_binary(&QueryResponse::success().genesis_metadata(ro_proceeded_state.get_metadata())) }, QueryMsg::Status(StatusMsg {}) => { let client_state = match get_client_state::(deps) { Ok(client_state) => client_state, - Err(_) => return to_binary(&QueryResponse::status("Unknown".to_string())), + Err(_) => return to_binary(&QueryResponse::success().status("Unknown".to_string())), }; if client_state.frozen_height().is_some() { - to_binary(&QueryResponse::status("Frozen".to_string())) + to_binary(&QueryResponse::success().status("Frozen".to_string())) } else { let height = client_state.latest_height(); match get_consensus_state(deps, &client_id, height) { @@ -362,13 +311,76 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { let tp = client_state.trusting_period.as_secs(); let now = env.block.time.seconds(); if (last_update + tp) < now { - return to_binary(&QueryResponse::status("Expired".to_string())) + return to_binary(&QueryResponse::success().status("Expired".to_string())) } - to_binary(&QueryResponse::status("Active".to_string())) + to_binary(&QueryResponse::success().status("Active".to_string())) }, - Err(_) => to_binary(&QueryResponse::status("Expired".to_string())), + Err(_) => to_binary(&QueryResponse::success().status("Expired".to_string())), } } }, + QueryMsg::TimestampAtHeight(msg) => { + let ctx = ContextReadOnly::::new(deps, env); + let consensus_state = ctx + .consensus_state(&client_id, msg.height) + .map_err(|e| ContractError::Tendermint(e.to_string()))?; + to_binary(&QueryResponse::success().timestamp(consensus_state.timestamp.unix_timestamp().unsigned_abs())) + }, + QueryMsg::VerifyClientMessage(msg) => { + let ctx = ContextReadOnly::::new(deps, env); + let client = TendermintClient::::default(); + let client_state = ctx + .client_state(&client_id) + .map_err(|e| ContractError::Tendermint(e.to_string()))?; + let msg = VerifyClientMessage::try_from(msg)?; + client + .verify_client_message(&ctx, client_id, client_state, msg.client_message) + .map_err(|e| ContractError::Tendermint(format!("{e:?}"))) + .map(|_| to_binary(&QueryResponse::success()))? + }, + QueryMsg::VerifyMembership(msg) => { + let ctx = ContextReadOnly::::new(deps, env); + let client_state = ctx + .client_state(&client_id) + .map_err(|e| ContractError::Tendermint(e.to_string()))?; + let msg = VerifyMembershipMsg::try_from(msg)?; + verify_delay_passed(&ctx, msg.height, msg.delay_time_period, msg.delay_block_period) + .map_err(|e| ContractError::Tendermint(e.to_string()))?; + let consensus_state = ctx + .consensus_state(&client_id, msg.height) + .map_err(|e| ContractError::Tendermint(e.to_string()))?; + verify_membership::( + &client_state, + &msg.prefix, + &msg.proof, + &consensus_state.root, + msg.path, + msg.value, + ) + .map_err(|e| ContractError::Tendermint(e.to_string()))?; + to_binary(&QueryResponse::success()) + }, + QueryMsg::VerifyNonMembership(msg) => { + let ctx = ContextReadOnly::::new(deps, env); + let client_state = ctx + .client_state(&client_id) + .map_err(|e| ContractError::Tendermint(e.to_string()))?; + let msg = VerifyNonMembershipMsg::try_from(msg)?; + verify_delay_passed(&ctx, msg.height, msg.delay_time_period, msg.delay_block_period) + .map_err(|e| ContractError::Tendermint(e.to_string()))?; + let consensus_state = ctx + .consensus_state(&client_id, msg.height) + .map_err(|e| ContractError::Tendermint(e.to_string()))?; + + verify_non_membership::( + &client_state, + &msg.prefix, + &msg.proof, + &consensus_state.root, + msg.path, + ) + .map_err(|e| ContractError::Tendermint(e.to_string())) + .map(|_| to_binary(&QueryResponse::success()))? + }, } } diff --git a/light-clients/ics07-tendermint-cw/src/error.rs b/light-clients/ics07-tendermint-cw/src/error.rs index 332ef6eb0..c694db223 100644 --- a/light-clients/ics07-tendermint-cw/src/error.rs +++ b/light-clients/ics07-tendermint-cw/src/error.rs @@ -55,3 +55,9 @@ impl From for ContractError { ContractError::Tendermint(e.to_string()) } } + +impl From for StdError { + fn from(e: ContractError) -> Self { + StdError::GenericErr { msg: e.to_string() } + } +} \ No newline at end of file diff --git a/light-clients/ics07-tendermint-cw/src/helpers.rs b/light-clients/ics07-tendermint-cw/src/helpers.rs index 50cd76841..c9e687b30 100644 --- a/light-clients/ics07-tendermint-cw/src/helpers.rs +++ b/light-clients/ics07-tendermint-cw/src/helpers.rs @@ -19,9 +19,10 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use crate::{ + context_read_only::ContextReadOnly, context::Context, ics23::{ConsensusStates, FakeInner, ProcessedStates}, - msg::ExecuteMsg, + msg::SudoMsg, }; use cosmwasm_std::{to_binary, Addr, CosmosMsg, StdResult, WasmMsg}; use ibc::core::{ @@ -61,14 +62,14 @@ impl CwTemplateContract { self.0.clone() } - pub fn call>(&self, msg: T) -> StdResult { + pub fn call>(&self, msg: T) -> StdResult { let msg = to_binary(&msg.into())?; Ok(WasmMsg::Execute { contract_addr: self.addr().into(), msg, funds: vec![] }.into()) } } pub fn verify_delay_passed( - ctx: &Context, + ctx: &ContextReadOnly, height: Height, delay_period_time: u64, delay_period_height: u64, diff --git a/light-clients/ics07-tendermint-cw/src/lib.rs b/light-clients/ics07-tendermint-cw/src/lib.rs index 478bc030b..e31a40301 100644 --- a/light-clients/ics07-tendermint-cw/src/lib.rs +++ b/light-clients/ics07-tendermint-cw/src/lib.rs @@ -19,6 +19,7 @@ extern crate core; mod channel; mod client; mod connection; +mod context_read_only; mod context; pub mod contract; mod error; diff --git a/light-clients/ics07-tendermint-cw/src/msg.rs b/light-clients/ics07-tendermint-cw/src/msg.rs index cc83e8100..c14e6bc82 100644 --- a/light-clients/ics07-tendermint-cw/src/msg.rs +++ b/light-clients/ics07-tendermint-cw/src/msg.rs @@ -57,18 +57,40 @@ pub struct GenesisMetadata { #[cw_serde] pub struct QueryResponse { - pub status: String, + pub is_valid: bool, + #[serde(skip_serializing_if = "Option::is_none")] + pub status: Option, #[serde(skip_serializing_if = "Option::is_none")] pub genesis_metadata: Option>, + #[serde(skip_serializing_if = "Option::is_none")] + pub found_misbehaviour: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub timestamp: Option, } impl QueryResponse { - pub fn status(status: String) -> Self { - Self { status, genesis_metadata: None } + pub fn success() -> Self { + Self { is_valid: true, status: None, genesis_metadata: None, found_misbehaviour: None, timestamp: None } + } + + pub fn status(mut self, status: String) -> Self { + self.status = Some(status); + self } - pub fn genesis_metadata(genesis_metadata: Option>) -> Self { - Self { status: "".to_string(), genesis_metadata } + pub fn genesis_metadata(mut self, genesis_metadata: Option>) -> Self { + self.genesis_metadata = genesis_metadata; + self + } + + pub fn misbehaviour(mut self, found_misbehavior: bool) -> Self { + self.found_misbehaviour = Some(found_misbehavior); + self + } + + pub fn timestamp(mut self, timestamp: u64) -> Self { + self.timestamp = Some(timestamp); + self } } @@ -78,21 +100,15 @@ pub struct ContractResult { pub error_msg: String, #[serde(skip_serializing_if = "Option::is_none")] pub data: Option>, - pub found_misbehaviour: bool, } impl ContractResult { pub fn success() -> Self { - Self { is_valid: true, error_msg: "".to_string(), data: None, found_misbehaviour: false } + Self { is_valid: true, error_msg: "".to_string(), data: None } } pub fn error(msg: String) -> Self { - Self { is_valid: false, error_msg: msg, data: None, found_misbehaviour: false } - } - - pub fn misbehaviour(mut self, found: bool) -> Self { - self.found_misbehaviour = found; - self + Self { is_valid: false, error_msg: msg, data: None } } pub fn data(mut self, data: Vec) -> Self { @@ -102,23 +118,29 @@ impl ContractResult { } #[cw_serde] -pub enum ExecuteMsg { - VerifyMembership(VerifyMembershipMsgRaw), - VerifyNonMembership(VerifyNonMembershipMsgRaw), - VerifyClientMessage(VerifyClientMessageRaw), - CheckForMisbehaviour(CheckForMisbehaviourMsgRaw), +pub enum SudoMsg { + CheckSubstituteAndUpdateState(CheckSubstituteAndUpdateStateMsg), UpdateStateOnMisbehaviour(UpdateStateOnMisbehaviourMsgRaw), UpdateState(UpdateStateMsgRaw), - CheckSubstituteAndUpdateState(CheckSubstituteAndUpdateStateMsg), VerifyUpgradeAndUpdateState(VerifyUpgradeAndUpdateStateMsgRaw), } #[cw_serde] pub enum QueryMsg { + CheckForMisbehaviour(CheckForMisbehaviourMsgRaw), ClientTypeMsg(ClientTypeMsg), GetLatestHeightsMsg(GetLatestHeightsMsg), ExportMetadata(ExportMetadataMsg), Status(StatusMsg), + TimestampAtHeight(TimestampAtHeightMsg), + VerifyMembership(VerifyMembershipMsgRaw), + VerifyNonMembership(VerifyNonMembershipMsgRaw), + VerifyClientMessage(VerifyClientMessageRaw), +} + +#[cw_serde] +pub struct TimestampAtHeightMsg { + pub height: Height, } #[cw_serde] From 0273593e1592bd045561238ce83e743c4ed38de7 Mon Sep 17 00:00:00 2001 From: Steve Miskovetz Date: Mon, 7 Aug 2023 12:14:04 -0600 Subject: [PATCH 05/37] Merge wasm header and misbehaviour to Client Message --- .../src/prost/ibc.lightclients.wasm.v1.rs | 13 +- light-clients/ics07-tendermint-cw/src/msg.rs | 31 ++--- .../ics08-wasm/src/client_message.rs | 128 ++---------------- 3 files changed, 25 insertions(+), 147 deletions(-) diff --git a/ibc/proto/src/prost/ibc.lightclients.wasm.v1.rs b/ibc/proto/src/prost/ibc.lightclients.wasm.v1.rs index 615c362c1..249d83d88 100644 --- a/ibc/proto/src/prost/ibc.lightclients.wasm.v1.rs +++ b/ibc/proto/src/prost/ibc.lightclients.wasm.v1.rs @@ -490,19 +490,10 @@ pub struct ConsensusState { // #[prost(uint64, tag = "2")] // pub timestamp: u64, } -/// Wasm light client Header +/// Wasm light client Client Message #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] -pub struct Header { - #[prost(bytes = "vec", tag = "1")] - pub data: ::prost::alloc::vec::Vec, - #[prost(message, optional, tag = "2")] - pub height: ::core::option::Option, -} -/// Wasm light client Misbehaviour -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Misbehaviour { +pub struct ClientMessage { #[prost(bytes = "vec", tag = "1")] pub data: ::prost::alloc::vec::Vec, } diff --git a/light-clients/ics07-tendermint-cw/src/msg.rs b/light-clients/ics07-tendermint-cw/src/msg.rs index c14e6bc82..8677d0729 100644 --- a/light-clients/ics07-tendermint-cw/src/msg.rs +++ b/light-clients/ics07-tendermint-cw/src/msg.rs @@ -18,7 +18,10 @@ use core::{str::FromStr, time::Duration}; use cosmwasm_schema::cw_serde; use ibc::{ core::{ - ics02_client::trust_threshold::TrustThreshold, + ics02_client::{ + trust_threshold::TrustThreshold, + error::Error, + }, ics23_commitment::commitment::{CommitmentPrefix, CommitmentProofBytes}, ics24_host::Path, }, @@ -27,11 +30,11 @@ use ibc::{ }; use ibc_proto::{google::protobuf::Any, ibc::core::client::v1::Height as HeightRaw}; use ics07_tendermint::{ - client_message::{ClientMessage, Header, Misbehaviour}, + client_message::{ClientMessage, Header, Misbehaviour, TENDERMINT_HEADER_TYPE_URL, TENDERMINT_MISBEHAVIOUR_TYPE_URL}, client_state::ClientState, }; use ics08_wasm::{ - client_message::Header as WasmHeader, client_state::ClientState as WasmClientState, + client_message::ClientMessage as WasmClientMessage, client_state::ClientState as WasmClientState, consensus_state::ConsensusState as WasmConsensusState, }; use prost::Message; @@ -246,18 +249,12 @@ impl TryFrom for VerifyNonMembershipMsg { } #[cw_serde] -pub struct WasmMisbehaviour { +pub struct ClientMessageRaw { #[schemars(with = "String")] #[serde(with = "Base64", default)] pub data: Bytes, } -#[cw_serde] -pub enum ClientMessageRaw { - Header(WasmHeader), - Misbehaviour(WasmMisbehaviour), -} - #[cw_serde] pub struct VerifyClientMessageRaw { pub client_message: ClientMessageRaw, @@ -278,15 +275,11 @@ impl TryFrom for VerifyClientMessage { impl VerifyClientMessage { fn decode_client_message(raw: ClientMessageRaw) -> Result { - let client_message = match raw { - ClientMessageRaw::Header(header) => { - let any = Any::decode(&mut header.data.as_slice())?; - ClientMessage::Header(Header::decode_vec(&any.value)?) - }, - ClientMessageRaw::Misbehaviour(misbehaviour) => { - let any = Any::decode(&mut misbehaviour.data.as_slice())?; - ClientMessage::Misbehaviour(Misbehaviour::decode_vec(&any.value)?) - }, + let any = Any::decode(raw.data.as_slice())?; + let client_message = match &*any.type_url { + TENDERMINT_HEADER_TYPE_URL => ClientMessage::Header(Header::decode_vec(&any.value)?), + TENDERMINT_MISBEHAVIOUR_TYPE_URL => ClientMessage::Misbehaviour(Misbehaviour::decode_vec(&any.value)?), + _ => return Err(ContractError::Tendermint("unknown client message type".to_string())), }; Ok(client_message) } diff --git a/light-clients/ics08-wasm/src/client_message.rs b/light-clients/ics08-wasm/src/client_message.rs index 84ea0e9c5..f51a271b9 100644 --- a/light-clients/ics08-wasm/src/client_message.rs +++ b/light-clients/ics08-wasm/src/client_message.rs @@ -31,33 +31,25 @@ use ibc::{ }; use ibc_proto::{ google::protobuf::Any, - ibc::lightclients::wasm::v1::{Header as RawHeader, Misbehaviour as RawMisbehaviour}, + ibc::lightclients::wasm::v1::ClientMessage as RawClientMessage, }; use prost::Message; -pub const WASM_HEADER_TYPE_URL: &str = "/ibc.lightclients.wasm.v1.Header"; -pub const WASM_MISBEHAVIOUR_TYPE_URL: &str = "/ibc.lightclients.wasm.v1.Misbehaviour"; pub const WASM_CLIENT_MESSAGE_TYPE_URL: &str = "/ibc.lightclients.wasm.v1.ClientMessage"; #[derive(Clone, Debug, PartialEq, Eq)] -pub enum ClientMessage { - Header(Header), - Misbehaviour(Misbehaviour), +pub struct ClientMessage { + pub inner: Box, + pub data: Bytes, } impl ClientMessage { pub fn inner(&self) -> &AnyClientMessage { - match self { - ClientMessage::Header(h) => &h.inner, - ClientMessage::Misbehaviour(m) => &m.inner, - } + &self.inner } pub fn into_inner(self) -> AnyClientMessage { - match self { - ClientMessage::Header(h) => *h.inner, - ClientMessage::Misbehaviour(m) => *m.inner, - } + *self.inner } } @@ -90,11 +82,8 @@ where fn try_from(any: Any) -> Result { let msg = match &*any.type_url { - WASM_HEADER_TYPE_URL => - Self::Header(Header::decode(&*any.value).map_err(|e| Error::decode_raw_header(e))?), - WASM_MISBEHAVIOUR_TYPE_URL => Self::Misbehaviour( - Misbehaviour::decode(&*any.value).map_err(Error::decode_raw_misbehaviour)?, - ), + WASM_CLIENT_MESSAGE_TYPE_URL => + ClientMessage::decode(&*any.value).map_err(|e| Error::decode_raw_header(e))?, _ => return Err(Error::malformed_header()), // TODO: choose a better error }; @@ -109,104 +98,9 @@ where >::Error: Display, { fn from(msg: ClientMessage) -> Self { - match msg { - ClientMessage::Header(header) => Any { - value: header.encode_vec().expect("encode header"), - type_url: WASM_HEADER_TYPE_URL.to_string(), - }, - ClientMessage::Misbehaviour(misbheaviour) => Any { - value: misbheaviour.encode_vec().expect("encode misbehaviour"), - type_url: WASM_MISBEHAVIOUR_TYPE_URL.to_string(), - }, + Any { + value: msg.encode_vec().expect("encode client message"), + type_url: WASM_CLIENT_MESSAGE_TYPE_URL.to_string(), } } } - -impl Protobuf for Misbehaviour -where - AnyClientMessage: Clone, - AnyClientMessage: TryFrom, - >::Error: Display, -{ -} - -impl TryFrom for Misbehaviour -where - AnyClientMessage: TryFrom, - >::Error: Display, -{ - type Error = String; - - fn try_from(raw: RawMisbehaviour) -> Result { - let any = Any::decode(&mut &raw.data[..]).map_err(|e| e.to_string())?; - let inner = AnyClientMessage::try_from(any).map_err(|e| e.to_string())?; - Ok(Self { inner: Box::new(inner), data: raw.data }) - } -} - -impl Protobuf for Header -where - AnyClientMessage: Clone, - AnyClientMessage: TryFrom, - >::Error: Display, -{ -} - -impl TryFrom for Header -where - AnyClientMessage: TryFrom, - >::Error: Display, -{ - type Error = String; - - fn try_from(raw: RawHeader) -> Result { - let any = Any::decode(&mut &raw.data[..]) - .map_err(|e| format!("failed to decode raw header into Any: {}", e.to_string()))?; - let inner = AnyClientMessage::try_from(any).map_err(|e| { - format!("failed to decode raw header into AnyClientMessage: {}", e.to_string()) - })?; - - let header = Self { - inner: Box::new(inner), - data: raw.data, - height: raw - .height - .ok_or_else(|| format!("failed to decode raw header into Header: missing height",))? - .into(), - }; - Ok(header) - } -} - -#[cfg_attr(feature = "cosmwasm", cw_serde)] -#[cfg_attr(not(feature = "cosmwasm"), derive(Clone, Debug, PartialEq))] -#[derive(Eq)] -pub struct Header { - #[cfg_attr(feature = "cosmwasm", serde(skip))] - #[cfg_attr(feature = "cosmwasm", schemars(skip))] - pub inner: Box, - #[cfg_attr(feature = "cosmwasm", schemars(with = "String"))] - #[cfg_attr(feature = "cosmwasm", serde(with = "Base64", default))] - pub data: Bytes, - pub height: Height, -} - -#[derive(Clone, Debug, PartialEq, Eq)] -pub struct Misbehaviour { - // #[schemars(with = "String")] - // #[serde(with = "Base64", default)] - pub inner: Box, - pub data: Bytes, -} - -impl From> for RawMisbehaviour { - fn from(value: Misbehaviour) -> Self { - RawMisbehaviour { data: value.data } - } -} - -impl From> for RawHeader { - fn from(value: Header) -> Self { - RawHeader { data: value.data, height: Some(value.height.into()) } - } -} From 98c62944646b58cc67d0f04d76d5cd8cf468a67b Mon Sep 17 00:00:00 2001 From: Steve Miskovetz Date: Mon, 7 Aug 2023 12:47:06 -0600 Subject: [PATCH 06/37] Return heights on update state --- .../ics07-tendermint-cw/src/contract.rs | 18 ++++++++++++------ light-clients/ics07-tendermint-cw/src/msg.rs | 11 +++++++++-- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/light-clients/ics07-tendermint-cw/src/contract.rs b/light-clients/ics07-tendermint-cw/src/contract.rs index 7d99a255f..3ae9c2da8 100644 --- a/light-clients/ics07-tendermint-cw/src/contract.rs +++ b/light-clients/ics07-tendermint-cw/src/contract.rs @@ -34,12 +34,15 @@ use crate::{ use cosmwasm_std::entry_point; use cosmwasm_std::{to_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult}; use ed25519_consensus::VerificationKey; -use ibc::core::{ - ics02_client::{ - client_def::{ClientDef, ConsensusUpdateResult}, - context::{ClientKeeper, ClientReader}, +use ibc::{ + core::{ + ics02_client::{ + client_def::{ClientDef, ConsensusUpdateResult}, + context::{ClientKeeper, ClientReader}, + }, + ics24_host::identifier::ClientId, }, - ics24_host::identifier::ClientId, + Height, }; use ibc_proto::google::protobuf::Any; use ics07_tendermint::{ @@ -215,13 +218,16 @@ fn process_message( .map_err(|e| ContractError::Tendermint(e.to_string())) .and_then(|(cs, cu)| { let height = cs.latest_height(); + let mut heights: Vec = vec![]; match cu { ConsensusUpdateResult::Single(cs) => { + heights.push(height); ctx.store_consensus_state(client_id.clone(), height, cs) .map_err(|e| ContractError::Tendermint(e.to_string()))?; }, ConsensusUpdateResult::Batch(css) => for (height, cs) in css { + heights.push(height); ctx.store_consensus_state(client_id.clone(), height, cs) .map_err(|e| ContractError::Tendermint(e.to_string()))?; }, @@ -230,7 +236,7 @@ fn process_message( ctx.store_client_state(client_id, cs) .map_err(|e| ContractError::Tendermint(e.to_string()))?; } - Ok(to_binary(&ContractResult::success())) + Ok(to_binary(&ContractResult::success().heights(heights))) }) }, SudoMsg::CheckSubstituteAndUpdateState(_msg) => diff --git a/light-clients/ics07-tendermint-cw/src/msg.rs b/light-clients/ics07-tendermint-cw/src/msg.rs index 8677d0729..6d528e441 100644 --- a/light-clients/ics07-tendermint-cw/src/msg.rs +++ b/light-clients/ics07-tendermint-cw/src/msg.rs @@ -103,21 +103,28 @@ pub struct ContractResult { pub error_msg: String, #[serde(skip_serializing_if = "Option::is_none")] pub data: Option>, + #[serde(skip_serializing_if = "Option::is_none")] + pub heights: Option>, } impl ContractResult { pub fn success() -> Self { - Self { is_valid: true, error_msg: "".to_string(), data: None } + Self { is_valid: true, error_msg: "".to_string(), data: None, heights: None } } pub fn error(msg: String) -> Self { - Self { is_valid: false, error_msg: msg, data: None } + Self { is_valid: false, error_msg: msg, data: None, heights: None } } pub fn data(mut self, data: Vec) -> Self { self.data = Some(data); self } + + pub fn heights(mut self, heights: Vec) -> Self { + self.heights = Some(heights); + self + } } #[cw_serde] From e8b24e2ba8eb6d27b928bea2cd0f0a70159d8583 Mon Sep 17 00:00:00 2001 From: Steve Miskovetz Date: Mon, 7 Aug 2023 13:31:38 -0600 Subject: [PATCH 07/37] Re-use context instead of adding a context for read only --- .../ics07-tendermint-cw/src/channel.rs | 114 +------- .../ics07-tendermint-cw/src/client.rs | 252 ------------------ .../ics07-tendermint-cw/src/connection.rs | 28 -- .../ics07-tendermint-cw/src/context.rs | 29 +- .../src/context_read_only.rs | 196 -------------- .../ics07-tendermint-cw/src/contract.rs | 12 +- .../ics07-tendermint-cw/src/helpers.rs | 3 +- light-clients/ics07-tendermint-cw/src/lib.rs | 1 - 8 files changed, 30 insertions(+), 605 deletions(-) delete mode 100644 light-clients/ics07-tendermint-cw/src/context_read_only.rs diff --git a/light-clients/ics07-tendermint-cw/src/channel.rs b/light-clients/ics07-tendermint-cw/src/channel.rs index a3aa5ba95..c48535bde 100644 --- a/light-clients/ics07-tendermint-cw/src/channel.rs +++ b/light-clients/ics07-tendermint-cw/src/channel.rs @@ -13,10 +13,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::{ - context::Context, - context_read_only::ContextReadOnly, -}; +use crate::context::Context; use ibc::{ core::{ ics04_channel::{ @@ -142,112 +139,3 @@ impl<'a, H: HostFunctionsProvider> ChannelReader for Context<'a, H> { unimplemented!("'max_expected_time_per_block' is unavailable from the client") } } - - -impl<'a, H: HostFunctionsProvider> ChannelReader for ContextReadOnly<'a, H> { - fn channel_end(&self, _port_channel_id: &(PortId, ChannelId)) -> Result { - Err(Error::implementation_specific( - "'channel_end' is unavailable from the client".to_string(), - )) - } - - fn connection_channels( - &self, - _conn_id: &ConnectionId, - ) -> Result, Error> { - Err(Error::implementation_specific( - "'connection_channels' is unavailable from the client".to_string(), - )) - } - - fn get_next_sequence_send( - &self, - _port_channel_id: &(PortId, ChannelId), - ) -> Result { - Err(Error::implementation_specific( - "'get_next_sequence_send' is unavailable from the client".to_string(), - )) - } - - fn get_next_sequence_recv( - &self, - _port_channel_id: &(PortId, ChannelId), - ) -> Result { - Err(Error::implementation_specific( - "'get_next_sequence_recv' is unavailable from the client".to_string(), - )) - } - - fn get_next_sequence_ack( - &self, - _port_channel_id: &(PortId, ChannelId), - ) -> Result { - Err(Error::implementation_specific( - "'get_next_sequence_ack' is unavailable from the client".to_string(), - )) - } - - fn get_packet_commitment( - &self, - _key: &(PortId, ChannelId, Sequence), - ) -> Result { - Err(Error::implementation_specific( - "'get_packet_commitment' is unavailable from the client".to_string(), - )) - } - - fn get_packet_receipt(&self, _key: &(PortId, ChannelId, Sequence)) -> Result { - Err(Error::implementation_specific( - "'get_packet_receipt' is unavailable from the client".to_string(), - )) - } - - fn get_packet_acknowledgement( - &self, - _key: &(PortId, ChannelId, Sequence), - ) -> Result { - Err(Error::implementation_specific( - "'get_packet_acknowledgement' is unavailable from the client".to_string(), - )) - } - - /// A hashing function for packet commitments - fn hash(&self, value: Vec) -> Vec { - let mut hasher = Sha256::default(); - hasher.update(value); - hasher.finalize().to_vec() - } - - fn client_update_time( - &self, - _client_id: &ClientId, - _height: Height, - ) -> Result { - Err(Error::implementation_specific( - "'client_update_time' is unavailable from the client".to_string(), - )) - } - - fn client_update_height( - &self, - _client_id: &ClientId, - _height: Height, - ) -> Result { - Err(Error::implementation_specific( - "'client_update_height' is unavailable from the client".to_string(), - )) - } - - /// Returns a counter on the number of channel ids have been created thus far. - /// The value of this counter should increase only via method - /// `ChannelKeeper::increase_channel_counter`. - fn channel_counter(&self) -> Result { - Err(Error::implementation_specific( - "'channel_counter' is unavailable from the client".to_string(), - )) - } - - fn max_expected_time_per_block(&self) -> Duration { - unimplemented!("'max_expected_time_per_block' is unavailable from the client") - } -} \ No newline at end of file diff --git a/light-clients/ics07-tendermint-cw/src/client.rs b/light-clients/ics07-tendermint-cw/src/client.rs index a74238284..af7b5f185 100644 --- a/light-clients/ics07-tendermint-cw/src/client.rs +++ b/light-clients/ics07-tendermint-cw/src/client.rs @@ -14,7 +14,6 @@ // limitations under the License. use crate::{ - context_read_only::ContextReadOnly, context::Context, ics23::{ ClientStates, ConsensusStates, FakeInner, ProcessedStates, ReadonlyClientStates, @@ -331,254 +330,3 @@ impl<'a, H: Clone> Context<'a, H> { wasm_consensus_state.to_any().encode_to_vec() } } - -/////////////////////////////////////////////////////////////////////////////////// - -impl<'a, H: HostFunctionsProvider + 'static> ClientTypes for ContextReadOnly<'a, H> { - type AnyClientMessage = ClientMessage; - type AnyClientState = ClientState; - type AnyConsensusState = ConsensusState; - type ClientDef = TendermintClient; -} - -impl<'a, H: HostFunctionsProvider + 'static> ClientReader for ContextReadOnly<'a, H> { - fn client_type(&self, client_id: &ClientId) -> Result { - let clients = ReadonlyClients::new(self.storage()); - if !clients.contains_key(client_id) { - return Err(Error::client_not_found(client_id.clone())) - } - - let data = clients - .get(client_id) - .ok_or_else(|| Error::client_not_found(client_id.clone()))?; - let data = String::from_utf8(data).map_err(|e| { - Error::implementation_specific(format!( - "[client_type]: error decoding client type bytes to string {}", - e - )) - })?; - match ClientType::from_str(&data) { - Err(_err) => Err(Error::unknown_client_type(data.to_string())), - Ok(val) => Ok(val), - } - } - - fn client_state(&self, client_id: &ClientId) -> Result, Error> { - let client_states = ReadonlyClientStates::new(self.storage()); - let data = client_states.get().ok_or_else(|| Error::client_not_found(client_id.clone()))?; - let state = Self::decode_client_state(&data)?; - Ok(state) - } - - fn consensus_state( - &self, - client_id: &ClientId, - height: Height, - ) -> Result { - let consensus_states = ReadonlyConsensusStates::new(self.storage()); - let value = consensus_states - .get(height) - .ok_or_else(|| Error::consensus_state_not_found(client_id.clone(), height))?; - let any_consensus_state = Self::decode_consensus_state(&value)?; - Ok(any_consensus_state) - } - - fn host_client_type(&self) -> String { - "ics07-tendermint".to_string() - } - - /// Similar to `consensus_state`, attempt to retrieve the consensus state, - /// but return `None` if no state exists at the given height. - /*fn maybe_consensus_state( - &self, - client_id: &ClientId, - height: Height, - ) -> Result, Error> { - unimplemented!() - //match self.consensus_state(client_id, height, &mut Vec::new()) { - // Ok(cs) => Ok(Some(cs)), - // Err(e) => match e.detail() { - // ErrorDetail::ConsensusStateNotFound(_) => Ok(None), - // _ => Err(e), - // }, - //} - }*/ - - fn next_consensus_state( - &self, - client_id: &ClientId, - height: Height, - ) -> Result, Error> { - let processed_state = ReadonlyProcessedStates::new(self.storage()); - match processed_state.get_next_height(height) { - Some(next_height) => self - .consensus_state(&client_id.clone(), next_height) - .and_then(|cs| Ok(Some(cs))), - None => Ok(None), - } - } - - fn prev_consensus_state( - &self, - client_id: &ClientId, - height: Height, - ) -> Result, Error> { - let processed_state = ReadonlyProcessedStates::new(self.storage()); - match processed_state.get_prev_height(height) { - Some(prev_height) => self - .consensus_state(&client_id.clone(), prev_height) - .and_then(|cs| Ok(Some(cs))), - None => Ok(None), - } - } - - fn host_height(&self) -> Height { - Height::new(0, self.env.block.height) - } - - fn host_timestamp(&self) -> Timestamp { - let time = self.env.block.time; - Timestamp::from_nanoseconds(time.nanos()).expect("invalid timestamp") - } - - fn host_consensus_state( - &self, - _height: Height, - _proof: Option>, - _client_state: &ClientState, - ) -> Result { - unimplemented!() - /*let consensus_state = - HOST_CONSENSUS_STATE.load(self.storage(), height.revision_height).map_err(|_| { - Error::implementation_specific(format!( - "[host_consensus_state]: consensus state not found for host at height {}", - height - )) - })?; - Ok(consensus_state)*/ - } - - fn client_counter(&self) -> Result { - unimplemented!() - /*let count = CLIENT_COUNTER.load(self.storage()).unwrap_or_default(); - log!(self, "in client : [client_counter] >> client_counter: {:?}", count); - Ok(count as u64)*/ - } -} - -impl<'a, H: HostFunctionsProvider + 'static> ClientKeeper for ContextReadOnly<'a, H> { - fn store_client_type( - &mut self, - _client_id: ClientId, - _client_type: ClientType, - ) -> Result<(), Error> { - unimplemented!() - } - - fn store_client_state( - &mut self, - client_id: ClientId, - client_state: Self::AnyClientState, - ) -> Result<(), Error> { - unimplemented!() - } - - fn store_consensus_state( - &mut self, - client_id: ClientId, - height: Height, - consensus_state: Self::AnyConsensusState, - ) -> Result<(), Error> { - unimplemented!() - } - - fn increase_client_counter(&mut self) { - unimplemented!() - } - - fn store_update_time( - &mut self, - _client_id: ClientId, - height: Height, - timestamp: Timestamp, - ) -> Result<(), Error> { - unimplemented!() - } - - fn store_update_height( - &mut self, - _client_id: ClientId, - height: Height, - host_height: Height, - ) -> Result<(), Error> { - unimplemented!() - } - - fn validate_self_client(&self, _client_state: &Self::AnyClientState) -> Result<(), Error> { - unimplemented!() - } -} - -impl<'a, H: Clone> ContextReadOnly<'a, H> { - pub fn decode_client_state(data: &[u8]) -> Result, Error> { - let any = Any::decode(data).map_err(Error::decode)?; - let wasm_state = - ics08_wasm::client_state::ClientState::::decode_vec( - &any.value, - ) - .map_err(|e| { - Error::implementation_specific(format!( - "[client_state]: error decoding client state bytes to WasmConsensusState {}", - e - )) - })?; - let any = Any::decode(&*wasm_state.data).map_err(|e| Error::decode(e))?; - let state = - ClientState::::decode_vec(&*any.value).map_err(Error::invalid_any_client_state)?; - Ok(state) - } - - pub fn decode_consensus_state(value: &[u8]) -> Result { - let any = Any::decode(&mut &*value).map_err(Error::decode)?; - let wasm_consensus_state = - ics08_wasm::consensus_state::ConsensusState::::decode_vec(&*any.value) - .map_err(Error::invalid_any_consensus_state)?; - let any = Any::decode(&mut &wasm_consensus_state.data[..]).map_err(Error::decode)?; - let any_consensus_state = - ConsensusState::decode_vec(&*any.value).map_err(Error::invalid_any_consensus_state)?; - Ok(any_consensus_state) - } - - pub fn encode_client_state( - client_state: ClientState, - code_hash: CodeHash, - // encoded_wasm_client_state: Vec, - ) -> Result, Error> { - // let any = Any::decode(&*encoded_wasm_client_state).map_err(Error::decode)?; - // let mut wasm_client_state = - // ics08_wasm::client_state::ClientState::::decode_vec( - // &any.value, - // ) - // .map_err(|e| { - // Error::implementation_specific(format!( - // "[client_state]: error decoding client state bytes to WasmConsensusState {}", - // e - // )) - // })?; - let mut wasm_client_state = - ics08_wasm::client_state::ClientState::::default(); - wasm_client_state.code_hash = code_hash; - wasm_client_state.data = client_state.to_any().encode_to_vec(); - wasm_client_state.latest_height = client_state.latest_height().into(); - let vec1 = wasm_client_state.to_any().encode_to_vec(); - Ok(vec1) - } - - pub fn encode_consensus_state(consensus_state: ConsensusState) -> Vec { - let wasm_consensus_state = ics08_wasm::consensus_state::ConsensusState { - data: consensus_state.to_any().encode_to_vec(), - inner: Box::new(FakeInner), - }; - wasm_consensus_state.to_any().encode_to_vec() - } -} diff --git a/light-clients/ics07-tendermint-cw/src/connection.rs b/light-clients/ics07-tendermint-cw/src/connection.rs index aeb6194cb..63ec8d486 100644 --- a/light-clients/ics07-tendermint-cw/src/connection.rs +++ b/light-clients/ics07-tendermint-cw/src/connection.rs @@ -14,7 +14,6 @@ // limitations under the License. use crate::{ - context_read_only::ContextReadOnly, context::Context, }; use ibc::{ @@ -48,33 +47,6 @@ impl<'a, H: HostFunctionsProvider> ConnectionReader for Context<'a, H> { unimplemented!("'commitment_prefix' is unavailable from the client"); } - fn connection_counter(&self) -> Result { - Err(Error::implementation_specific( - "'connection_counter' is unavailable from the client".to_string(), - )) - } -} - -impl<'a, H: HostFunctionsProvider> ConnectionReader for ContextReadOnly<'a, H> { - fn minimum_delay_period(&self) -> Duration { - unimplemented!("minimum_delay_period") - } - - fn connection_end(&self, _conn_id: &ConnectionId) -> Result { - Err(Error::implementation_specific( - "'connection_end' is unavailable from the client".to_string(), - )) - } - - fn host_oldest_height(&self) -> Height { - unimplemented!("the method should be removed in the future"); - } - - #[allow(clippy::disallowed_methods)] - fn commitment_prefix(&self) -> CommitmentPrefix { - unimplemented!("'commitment_prefix' is unavailable from the client"); - } - fn connection_counter(&self) -> Result { Err(Error::implementation_specific( "'connection_counter' is unavailable from the client".to_string(), diff --git a/light-clients/ics07-tendermint-cw/src/context.rs b/light-clients/ics07-tendermint-cw/src/context.rs index 81a4f76c0..565fa7437 100644 --- a/light-clients/ics07-tendermint-cw/src/context.rs +++ b/light-clients/ics07-tendermint-cw/src/context.rs @@ -20,7 +20,7 @@ use crate::{ }, ContractError, }; -use cosmwasm_std::{DepsMut, Env, Storage}; +use cosmwasm_std::{Deps, DepsMut, Env, Storage}; use ibc::{ core::{ ics02_client::{error::Error, events::CodeHash}, @@ -36,7 +36,8 @@ use ics07_tendermint::{ use std::{fmt, fmt::Debug, marker::PhantomData}; pub struct Context<'a, H> { - pub deps: DepsMut<'a>, + pub deps_mut: Option>, + pub deps: Option>, pub env: Env, pub code_hash: Option, _phantom: PhantomData, @@ -64,19 +65,35 @@ impl<'a, H> Clone for Context<'a, H> { impl<'a, H> Context<'a, H> { pub fn new(deps: DepsMut<'a>, env: Env) -> Self { - Self { deps, _phantom: Default::default(), env, code_hash: None } + Self { deps_mut: Some(deps), deps: None, _phantom: Default::default(), env, code_hash: None } + } + + pub fn new_ro(deps: Deps<'a>, env: Env) -> Self { + Self { deps_mut: None, deps: Some(deps), _phantom: Default::default(), env, code_hash: None } } pub fn log(&self, msg: &str) { - self.deps.api.debug(msg) + match &self.deps_mut { + Some(deps_mut) => deps_mut.api.debug(msg), + None => unimplemented!() + } } pub fn storage(&self) -> &dyn Storage { - self.deps.storage + match &self.deps_mut { + Some(deps_mut) => deps_mut.storage, + None => match &self.deps { + Some(deps) => deps.storage, + None => unimplemented!() + } + } } pub fn storage_mut(&mut self) -> &mut dyn Storage { - self.deps.storage + match &mut self.deps_mut { + Some(deps_mut) => deps_mut.storage, + None => unimplemented!() + } } } diff --git a/light-clients/ics07-tendermint-cw/src/context_read_only.rs b/light-clients/ics07-tendermint-cw/src/context_read_only.rs deleted file mode 100644 index 011fd7ba3..000000000 --- a/light-clients/ics07-tendermint-cw/src/context_read_only.rs +++ /dev/null @@ -1,196 +0,0 @@ -// Copyright (C) 2022 ComposableFi. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use crate::{ - ics23::{ - ClientStates, ConsensusStates, FakeInner, ReadonlyClientStates, ReadonlyConsensusStates, - ReadonlyProcessedStates, - }, - ContractError, -}; -use cosmwasm_std::{Deps, Env, Storage}; -use ibc::{ - core::{ - ics02_client::{error::Error, events::CodeHash}, - ics24_host::identifier::ClientId, - ics26_routing::context::ReaderContext, - }, - Height, -}; -use ibc_proto::google::protobuf::Any; -use ics07_tendermint::{ - client_state::ClientState, consensus_state::ConsensusState, HostFunctionsProvider, -}; -use std::{fmt, fmt::Debug, marker::PhantomData}; - -pub struct ContextReadOnly<'a, H> { - pub deps: Deps<'a>, - pub env: Env, - pub code_hash: Option, - _phantom: PhantomData, -} - -impl<'a, H> PartialEq for ContextReadOnly<'a, H> { - fn eq(&self, _other: &Self) -> bool { - true - } -} - -impl<'a, H> Eq for ContextReadOnly<'a, H> {} - -impl<'a, H> Debug for ContextReadOnly<'a, H> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "ContextReadOnly {{ deps: DepsMut }}") - } -} - -impl<'a, H> Clone for ContextReadOnly<'a, H> { - fn clone(&self) -> Self { - panic!("ContextReadOnly is not cloneable") - } -} - -impl<'a, H> ContextReadOnly<'a, H> { - pub fn new(deps: Deps<'a>, env: Env) -> Self { - Self { deps, _phantom: Default::default(), env, code_hash: None } - } - - //pub fn log(&self, msg: &str) { - // self.deps.api.debug(msg) - //} - - pub fn storage(&self) -> &dyn Storage { - self.deps.storage - } - - //pub fn storage_mut(&mut self) -> &mut dyn Storage { - // self.deps.storage - //} -} - -impl<'a, H> ContextReadOnly<'a, H> -where - H: Clone, -{ - pub fn processed_timestamp(&self, height: Height) -> Result { - let processed_state = ReadonlyProcessedStates::new(self.storage()); - match processed_state.get_processed_time(height, &mut Vec::new()) { - Some(time) => Ok(time), - None => ibc::prelude::Err(Error::implementation_specific(format!( - "problem getting processed timestamp" - ))), - } - } - - pub fn processed_height(&self, height: Height) -> Result { - let processed_state = ReadonlyProcessedStates::new(self.storage()); - match processed_state.get_processed_height(height, &mut Vec::new()) { - Some(p_height) => Ok(p_height), - None => ibc::prelude::Err(Error::implementation_specific(format!( - "problem getting processed height" - ))), - } - } - - pub fn consensus_state_prefixed( - &self, - height: Height, - prefix: &[u8], - ) -> Result { - let bytes = ReadonlyConsensusStates::new(self.storage()) - .get_prefixed(height, prefix) - .ok_or_else(|| { - ContractError::Tendermint(format!( - "no consensus state found for height {} and prefix {:?}", - height, prefix, - )) - })?; - ContextReadOnly::::decode_consensus_state(&bytes).map_err(|e| { - ContractError::Tendermint(format!("error decoding consensus state: {:?}", e)) - }) - } -} - -/* pub fn store_consensus_state_prefixed( - &mut self, - height: Height, - consensus_state: ConsensusState, - prefix: &[u8], - ) { - let encoded = Context::::encode_consensus_state(consensus_state); - let mut consensus_states = ConsensusStates::new(self.storage_mut()); - consensus_states.insert_prefixed(height, encoded, prefix); - } - - pub fn client_state_prefixed(&self, prefix: &[u8]) -> Result, ContractError> { - let bytes = - ReadonlyClientStates::new(self.storage()).get_prefixed(prefix).ok_or_else(|| { - ContractError::Tendermint(format!("no client state found for prefix {:?}", prefix,)) - })?; - Context::decode_client_state(&bytes) - .map_err(|e| ContractError::Tendermint(format!("error decoding client state: {:?}", e))) - } - - pub fn store_client_state_prefixed( - &mut self, - client_state: ClientState, - prefix: &[u8], - ) -> Result<(), ContractError> { - use prost::Message; - use tendermint_proto::Protobuf; - let client_states = ReadonlyClientStates::new(self.storage()); - // let data = client_states.get_prefixed(prefix).ok_or_else(|| { - // ContractError::Tendermint("no client state found for prefix".to_string()) - // })?; - let code_hash = match self.code_hash.clone() { - None => { - let encoded_wasm_client_state = client_states.get().ok_or_else(|| { - ContractError::Tendermint( - Error::client_not_found(ClientId::new("x", 1).unwrap()).to_string(), - ) - })?; - let any = Any::decode(&*encoded_wasm_client_state) - .map_err(Error::decode) - .map_err(|e| ContractError::Tendermint(e.to_string()))?; - let wasm_client_state = ics08_wasm::client_state::ClientState::< - FakeInner, - FakeInner, - FakeInner, - >::decode_vec(&any.value) - .map_err(|e| { - ContractError::Tendermint( - Error::implementation_specific(format!( - "[client_state]: error decoding client state bytes to WasmConsensusState {}", - e - )) - .to_string(), - ) - })?; - wasm_client_state.code_hash - }, - Some(x) => x, - }; - - let encoded = Context::::encode_client_state(client_state, code_hash).map_err(|e| { - ContractError::Tendermint(format!("error encoding client state: {:?}", e)) - })?; - let mut client_states = ClientStates::new(self.storage_mut()); - client_states.insert_prefixed(encoded, prefix); - Ok(()) - } -}*/ - -impl<'a, H: HostFunctionsProvider + 'static> ReaderContext for ContextReadOnly<'a, H> {} - diff --git a/light-clients/ics07-tendermint-cw/src/contract.rs b/light-clients/ics07-tendermint-cw/src/contract.rs index 3ae9c2da8..3aab249f9 100644 --- a/light-clients/ics07-tendermint-cw/src/contract.rs +++ b/light-clients/ics07-tendermint-cw/src/contract.rs @@ -15,7 +15,6 @@ use crate::{ context::Context, - context_read_only::ContextReadOnly, error::ContractError, helpers::{ check_substitute_and_update_state, prune_oldest_consensus_state, verify_delay_passed, @@ -281,10 +280,9 @@ fn process_message( #[cfg_attr(not(feature = "library"), entry_point)] pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { let client_id = ClientId::from_str("08-wasm-0").expect("client id is valid"); - //deps.api.debug("In query"); match msg { QueryMsg::CheckForMisbehaviour(msg) => { - let ctx = ContextReadOnly::::new(deps, env); + let ctx = Context::::new_ro(deps, env); let client = TendermintClient::::default(); let client_state = ctx .client_state(&client_id) @@ -326,14 +324,14 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { } }, QueryMsg::TimestampAtHeight(msg) => { - let ctx = ContextReadOnly::::new(deps, env); + let ctx = Context::::new_ro(deps, env); let consensus_state = ctx .consensus_state(&client_id, msg.height) .map_err(|e| ContractError::Tendermint(e.to_string()))?; to_binary(&QueryResponse::success().timestamp(consensus_state.timestamp.unix_timestamp().unsigned_abs())) }, QueryMsg::VerifyClientMessage(msg) => { - let ctx = ContextReadOnly::::new(deps, env); + let ctx = Context::::new_ro(deps, env); let client = TendermintClient::::default(); let client_state = ctx .client_state(&client_id) @@ -345,7 +343,7 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { .map(|_| to_binary(&QueryResponse::success()))? }, QueryMsg::VerifyMembership(msg) => { - let ctx = ContextReadOnly::::new(deps, env); + let ctx = Context::::new_ro(deps, env); let client_state = ctx .client_state(&client_id) .map_err(|e| ContractError::Tendermint(e.to_string()))?; @@ -367,7 +365,7 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { to_binary(&QueryResponse::success()) }, QueryMsg::VerifyNonMembership(msg) => { - let ctx = ContextReadOnly::::new(deps, env); + let ctx = Context::::new_ro(deps, env); let client_state = ctx .client_state(&client_id) .map_err(|e| ContractError::Tendermint(e.to_string()))?; diff --git a/light-clients/ics07-tendermint-cw/src/helpers.rs b/light-clients/ics07-tendermint-cw/src/helpers.rs index c9e687b30..63874456f 100644 --- a/light-clients/ics07-tendermint-cw/src/helpers.rs +++ b/light-clients/ics07-tendermint-cw/src/helpers.rs @@ -19,7 +19,6 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use crate::{ - context_read_only::ContextReadOnly, context::Context, ics23::{ConsensusStates, FakeInner, ProcessedStates}, msg::SudoMsg, @@ -69,7 +68,7 @@ impl CwTemplateContract { } pub fn verify_delay_passed( - ctx: &ContextReadOnly, + ctx: &Context, height: Height, delay_period_time: u64, delay_period_height: u64, diff --git a/light-clients/ics07-tendermint-cw/src/lib.rs b/light-clients/ics07-tendermint-cw/src/lib.rs index e31a40301..478bc030b 100644 --- a/light-clients/ics07-tendermint-cw/src/lib.rs +++ b/light-clients/ics07-tendermint-cw/src/lib.rs @@ -19,7 +19,6 @@ extern crate core; mod channel; mod client; mod connection; -mod context_read_only; mod context; pub mod contract; mod error; From f65155aa477bbf454744d84411dc50cc18efe2ef Mon Sep 17 00:00:00 2001 From: Steve Miskovetz Date: Mon, 7 Aug 2023 16:29:27 -0600 Subject: [PATCH 08/37] clean up imports --- light-clients/ics07-tendermint-cw/src/client.rs | 1 - light-clients/ics07-tendermint-cw/src/connection.rs | 4 +--- light-clients/ics07-tendermint-cw/src/msg.rs | 7 ++----- light-clients/ics08-wasm/src/client_message.rs | 11 ++--------- light-clients/ics08-wasm/src/consensus_state.rs | 2 +- 5 files changed, 6 insertions(+), 19 deletions(-) diff --git a/light-clients/ics07-tendermint-cw/src/client.rs b/light-clients/ics07-tendermint-cw/src/client.rs index af7b5f185..70989d81a 100644 --- a/light-clients/ics07-tendermint-cw/src/client.rs +++ b/light-clients/ics07-tendermint-cw/src/client.rs @@ -23,7 +23,6 @@ use crate::{ use ibc::{ core::{ ics02_client::{ - client_consensus::ConsensusState as _, client_state::ClientType, context::{ClientKeeper, ClientReader, ClientTypes}, error::Error, diff --git a/light-clients/ics07-tendermint-cw/src/connection.rs b/light-clients/ics07-tendermint-cw/src/connection.rs index 63ec8d486..ba6a4e8c6 100644 --- a/light-clients/ics07-tendermint-cw/src/connection.rs +++ b/light-clients/ics07-tendermint-cw/src/connection.rs @@ -13,9 +13,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::{ - context::Context, -}; +use crate::context::Context; use ibc::{ core::{ ics03_connection::{connection::ConnectionEnd, context::ConnectionReader, error::Error}, diff --git a/light-clients/ics07-tendermint-cw/src/msg.rs b/light-clients/ics07-tendermint-cw/src/msg.rs index 6d528e441..f5572a262 100644 --- a/light-clients/ics07-tendermint-cw/src/msg.rs +++ b/light-clients/ics07-tendermint-cw/src/msg.rs @@ -18,10 +18,7 @@ use core::{str::FromStr, time::Duration}; use cosmwasm_schema::cw_serde; use ibc::{ core::{ - ics02_client::{ - trust_threshold::TrustThreshold, - error::Error, - }, + ics02_client::trust_threshold::TrustThreshold, ics23_commitment::commitment::{CommitmentPrefix, CommitmentProofBytes}, ics24_host::Path, }, @@ -34,7 +31,7 @@ use ics07_tendermint::{ client_state::ClientState, }; use ics08_wasm::{ - client_message::ClientMessage as WasmClientMessage, client_state::ClientState as WasmClientState, + client_state::ClientState as WasmClientState, consensus_state::ConsensusState as WasmConsensusState, }; use prost::Message; diff --git a/light-clients/ics08-wasm/src/client_message.rs b/light-clients/ics08-wasm/src/client_message.rs index f51a271b9..d94b04321 100644 --- a/light-clients/ics08-wasm/src/client_message.rs +++ b/light-clients/ics08-wasm/src/client_message.rs @@ -14,26 +14,19 @@ // limitations under the License. #[cfg(feature = "cosmwasm")] -use crate::msg::Base64; use crate::Bytes; use alloc::{ boxed::Box, - string::{String, ToString}, + string::ToString, vec::Vec, }; use core::fmt::Display; #[cfg(feature = "cosmwasm")] -use cosmwasm_schema::cw_serde; use ibc::{ core::ics02_client::{client_message::ClientMessage as IbcClientMessage, error::Error}, protobuf::Protobuf, - Height, }; -use ibc_proto::{ - google::protobuf::Any, - ibc::lightclients::wasm::v1::ClientMessage as RawClientMessage, -}; -use prost::Message; +use ibc_proto::google::protobuf::Any; pub const WASM_CLIENT_MESSAGE_TYPE_URL: &str = "/ibc.lightclients.wasm.v1.ClientMessage"; diff --git a/light-clients/ics08-wasm/src/consensus_state.rs b/light-clients/ics08-wasm/src/consensus_state.rs index 4da5b79c4..7230b069d 100644 --- a/light-clients/ics08-wasm/src/consensus_state.rs +++ b/light-clients/ics08-wasm/src/consensus_state.rs @@ -30,7 +30,7 @@ use cosmwasm_schema::cw_serde; use ibc::{ core::{ ics02_client::client_consensus::{ - ConsensusState as IcsConsensusState, ConsensusState as _, + ConsensusState as IcsConsensusState, ConsensusState as IbcConsensusState, }, ics23_commitment::commitment::CommitmentRoot, From 7b258708f0868cadf1dde50208dd08268c164486 Mon Sep 17 00:00:00 2001 From: Steve Miskovetz Date: Thu, 17 Aug 2023 17:31:52 -0600 Subject: [PATCH 09/37] Update grandpa --- light-clients/ics10-grandpa-cw/src/client.rs | 1 - light-clients/ics10-grandpa-cw/src/context.rs | 29 ++- .../ics10-grandpa-cw/src/contract.rs | 204 +++++++++--------- light-clients/ics10-grandpa-cw/src/error.rs | 6 + light-clients/ics10-grandpa-cw/src/helpers.rs | 4 +- light-clients/ics10-grandpa-cw/src/msg.rs | 93 ++++---- 6 files changed, 190 insertions(+), 147 deletions(-) diff --git a/light-clients/ics10-grandpa-cw/src/client.rs b/light-clients/ics10-grandpa-cw/src/client.rs index 5c058a44a..cbf9dc150 100644 --- a/light-clients/ics10-grandpa-cw/src/client.rs +++ b/light-clients/ics10-grandpa-cw/src/client.rs @@ -26,7 +26,6 @@ use grandpa_light_client_primitives::HostFunctions; use ibc::{ core::{ ics02_client::{ - client_consensus::ConsensusState as _, client_state::ClientType, context::{ClientKeeper, ClientReader, ClientTypes}, error::Error, diff --git a/light-clients/ics10-grandpa-cw/src/context.rs b/light-clients/ics10-grandpa-cw/src/context.rs index d24db38a7..ffc5ce3c2 100644 --- a/light-clients/ics10-grandpa-cw/src/context.rs +++ b/light-clients/ics10-grandpa-cw/src/context.rs @@ -23,7 +23,7 @@ use crate::{ }, ContractError, }; -use cosmwasm_std::{DepsMut, Env, Storage}; +use cosmwasm_std::{Deps, DepsMut, Env, Storage}; use grandpa_light_client_primitives::HostFunctions; use ibc::{ core::{ @@ -41,7 +41,8 @@ use sp_core::H256; use std::{fmt, fmt::Debug, marker::PhantomData}; pub struct Context<'a, H> { - pub deps: DepsMut<'a>, + pub deps_mut: Option>, + pub deps: Option>, pub env: Env, pub code_hash: Option, _phantom: PhantomData, @@ -69,19 +70,35 @@ impl<'a, H> Clone for Context<'a, H> { impl<'a, H> Context<'a, H> { pub fn new(deps: DepsMut<'a>, env: Env) -> Self { - Self { deps, _phantom: Default::default(), env, code_hash: None } + Self { deps_mut: Some(deps), deps: None, _phantom: Default::default(), env, code_hash: None } + } + + pub fn new_ro(deps: Deps<'a>, env: Env) -> Self { + Self { deps_mut: None, deps: Some(deps), _phantom: Default::default(), env, code_hash: None } } pub fn log(&self, msg: &str) { - self.deps.api.debug(msg) + match &self.deps_mut { + Some(deps_mut) => deps_mut.api.debug(msg), + None => unimplemented!() + } } pub fn storage(&self) -> &dyn Storage { - self.deps.storage + match &self.deps_mut { + Some(deps_mut) => deps_mut.storage, + None => match &self.deps { + Some(deps) => deps.storage, + None => unimplemented!() + } + } } pub fn storage_mut(&mut self) -> &mut dyn Storage { - self.deps.storage + match &mut self.deps_mut { + Some(deps_mut) => deps_mut.storage, + None => unimplemented!() + } } pub fn insert_relay_header_hashes(&mut self, headers: &[H256]) { diff --git a/light-clients/ics10-grandpa-cw/src/contract.rs b/light-clients/ics10-grandpa-cw/src/contract.rs index ea722b876..e0730fe98 100644 --- a/light-clients/ics10-grandpa-cw/src/contract.rs +++ b/light-clients/ics10-grandpa-cw/src/contract.rs @@ -19,8 +19,8 @@ use crate::{ ics23::FakeInner, log, msg::{ - CheckForMisbehaviourMsg, CheckSubstituteAndUpdateStateMsg, ClientStateCallResponse, - ContractResult, ExecuteMsg, ExportMetadataMsg, InitializeState, QueryMsg, QueryResponse, + CheckForMisbehaviourMsg, CheckSubstituteAndUpdateStateMsg, + ContractResult, SudoMsg, ExportMetadataMsg, QueryMsg, QueryResponse, StatusMsg, UpdateStateMsg, UpdateStateOnMisbehaviourMsg, VerifyClientMessage, VerifyMembershipMsg, VerifyNonMembershipMsg, VerifyUpgradeAndUpdateStateMsg, }, @@ -153,11 +153,10 @@ pub fn instantiate( } #[cfg_attr(not(feature = "library"), entry_point)] -pub fn execute( +pub fn sudo( deps: DepsMut, env: Env, - _info: MessageInfo, - msg: ExecuteMsg, + msg: SudoMsg, ) -> Result { let client = GrandpaClient::::default(); let mut ctx = Context::::new(deps, env); @@ -169,86 +168,14 @@ pub fn execute( } fn process_message( - msg: ExecuteMsg, + msg: SudoMsg, client: GrandpaClient, ctx: &mut Context, client_id: ClientId, ) -> Result { // log!(ctx, "process_message: {:?}", msg); let result = match msg { - ExecuteMsg::VerifyMembership(msg) => { - let msg = VerifyMembershipMsg::try_from(msg)?; - let consensus_state = ctx - .consensus_state(&client_id, msg.height) - .map_err(|e| ContractError::Grandpa(e.to_string()))?; - verify_membership::( - &msg.prefix, - &msg.proof, - &consensus_state.root, - msg.path, - msg.value, - ) - .map_err(|e| ContractError::Grandpa(e.to_string()))?; - Ok(()).map(|_| to_binary(&ContractResult::success())) - }, - ExecuteMsg::VerifyNonMembership(msg) => { - let msg = VerifyNonMembershipMsg::try_from(msg)?; - let consensus_state = ctx - .consensus_state(&client_id, msg.height) - .map_err(|e| ContractError::Grandpa(e.to_string()))?; - - verify_non_membership::( - &msg.prefix, - &msg.proof, - &consensus_state.root, - msg.path, - ) - .map_err(|e| ContractError::Grandpa(e.to_string())) - .map(|_| to_binary(&ContractResult::success())) - }, - ExecuteMsg::VerifyClientMessage(msg) => { - let client_state = ctx - .client_state(&client_id) - .map_err(|e| ContractError::Grandpa(e.to_string()))?; - let msg = VerifyClientMessage::try_from(msg)?; - - match &msg.client_message { - ClientMessage::Misbehaviour(misbehavior) => { - let first_proof = &misbehavior.first_finality_proof; - let first_base = first_proof - .unknown_headers - .iter() - .min_by_key(|h| *h.number()) - .ok_or_else(|| { - ContractError::Grandpa("Unknown headers can't be empty!".to_string()) - })?; - let first_parent = first_base.parent_hash; - if !ctx.contains_relay_header_hash(first_parent) { - Err(ContractError::Grandpa( - "Could not find the known header for first finality proof".to_string(), - ))? - } - }, - _ => {}, - } - - let f = client - .verify_client_message(ctx, client_id, client_state, msg.client_message) - .map_err(|e| ContractError::Grandpa(format!("{e:?}"))) - .map(|_| to_binary(&ContractResult::success())); - f - }, - ExecuteMsg::CheckForMisbehaviour(msg) => { - let client_state = ctx - .client_state(&client_id) - .map_err(|e| ContractError::Grandpa(e.to_string()))?; - let msg = CheckForMisbehaviourMsg::try_from(msg)?; - client - .check_for_misbehaviour(ctx, client_id, client_state, msg.client_message) - .map_err(|e| ContractError::Grandpa(e.to_string())) - .map(|result| to_binary(&ContractResult::success().misbehaviour(result))) - }, - ExecuteMsg::UpdateStateOnMisbehaviour(msg_raw) => { + SudoMsg::UpdateStateOnMisbehaviour(msg_raw) => { let client_state = ctx .client_state(&client_id) .map_err(|e| ContractError::Grandpa(e.to_string()))?; @@ -262,7 +189,7 @@ fn process_message( Ok(to_binary(&ContractResult::success())) }) }, - ExecuteMsg::UpdateState(msg_raw) => { + SudoMsg::UpdateState(msg_raw) => { let client_state = ctx .client_state(&client_id) .map_err(|e| ContractError::Grandpa(e.to_string()))?; @@ -293,7 +220,7 @@ fn process_message( store_client_and_consensus_states(ctx, client_id.clone(), cs, cu) }) }, - ExecuteMsg::CheckSubstituteAndUpdateState(msg) => { + SudoMsg::CheckSubstituteAndUpdateState(msg) => { let _msg = CheckSubstituteAndUpdateStateMsg::try_from(msg)?; // manually load both states from the combined storage using the appropriate prefixes let mut old_client_state = ctx @@ -332,7 +259,7 @@ fn process_message( Ok(()).map(|_| to_binary(&ContractResult::success())) }, - ExecuteMsg::VerifyUpgradeAndUpdateState(msg) => { + SudoMsg::VerifyUpgradeAndUpdateState(msg) => { let old_client_state = ctx .client_state(&client_id) .map_err(|e| ContractError::Grandpa(e.to_string()))?; @@ -353,45 +280,119 @@ fn process_message( store_client_and_consensus_states(ctx, client_id.clone(), cs, cu) }) }, - ExecuteMsg::InitializeState(InitializeState { client_state, consensus_state }) => { - let state_call_response = ClientStateCallResponse { - new_consensus_state: consensus_state.clone(), - new_client_state: client_state.clone(), - client_state, - result: ContractResult::success(), - }; - let response = to_binary(&state_call_response); - Ok(response) - }, - ExecuteMsg::ClientCreateRequest(_) => Ok(to_binary(&ContractResult::success())), }; Ok(result??) } #[cfg_attr(not(feature = "library"), entry_point)] -pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { +pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { let client_id = ClientId::from_str("08-wasm-0").expect("client id is valid"); match msg { + QueryMsg::CheckForMisbehaviour(msg) => { + let ctx = Context::::new_ro(deps, env); + let client = GrandpaClient::::default(); + let client_state = ctx + .client_state(&client_id) + .map_err(|e| ContractError::Grandpa(e.to_string()))?; + let msg = CheckForMisbehaviourMsg::try_from(msg)?; + client + .check_for_misbehaviour(&ctx, client_id, client_state, msg.client_message) + .map_err(|e| ContractError::Grandpa(e.to_string())) + .map(|result| to_binary(&QueryResponse::success().misbehaviour(result)))? + }, QueryMsg::ClientTypeMsg(_) => unimplemented!("ClientTypeMsg"), QueryMsg::GetLatestHeightsMsg(_) => unimplemented!("GetLatestHeightsMsg"), QueryMsg::ExportMetadata(ExportMetadataMsg {}) => - to_binary(&QueryResponse::genesis_metadata(None)), + to_binary(&QueryResponse::success().genesis_metadata(None)), QueryMsg::Status(StatusMsg {}) => { let client_state = match get_client_state::(deps) { Ok(client_state) => client_state, - Err(_) => return to_binary(&QueryResponse::status("Unknown".to_string())), + Err(_) => return to_binary(&QueryResponse::success().status("Unknown".to_string())), }; if client_state.frozen_height().is_some() { - to_binary(&QueryResponse::status("Frozen".to_string())) + to_binary(&QueryResponse::success().status("Frozen".to_string())) } else { let height = client_state.latest_height(); match get_consensus_state(deps, &client_id, height) { - Ok(_) => to_binary(&QueryResponse::status("Active".to_string())), - Err(_) => to_binary(&QueryResponse::status("Expired".to_string())), + Ok(_) => to_binary(&QueryResponse::success().status("Active".to_string())), + Err(_) => to_binary(&QueryResponse::success().status("Expired".to_string())), } } }, + QueryMsg::TimestampAtHeight(msg) => { + let ctx = Context::::new_ro(deps, env); + let consensus_state = ctx + .consensus_state(&client_id, msg.height) + .map_err(|e| ContractError::Grandpa(e.to_string()))?; + to_binary(&QueryResponse::success().timestamp(consensus_state.timestamp.unix_timestamp().unsigned_abs())) + }, + QueryMsg::VerifyClientMessage(msg) => { + let ctx = Context::::new_ro(deps, env); + let client = GrandpaClient::::default(); + let client_state = ctx + .client_state(&client_id) + .map_err(|e| ContractError::Grandpa(e.to_string()))?; + let msg = VerifyClientMessage::try_from(msg)?; + + match &msg.client_message { + ClientMessage::Misbehaviour(misbehavior) => { + let first_proof = &misbehavior.first_finality_proof; + let first_base = first_proof + .unknown_headers + .iter() + .min_by_key(|h| *h.number()) + .ok_or_else(|| { + ContractError::Grandpa("Unknown headers can't be empty!".to_string()) + })?; + let first_parent = first_base.parent_hash; + if !ctx.contains_relay_header_hash(first_parent) { + Err(ContractError::Grandpa( + "Could not find the known header for first finality proof".to_string(), + ))? + } + }, + _ => {}, + } + + let f = client + .verify_client_message(&ctx, client_id, client_state, msg.client_message) + .map_err(|e| ContractError::Grandpa(format!("{e:?}"))) + .map(|_| to_binary(&QueryResponse::success()))?; + f + }, + QueryMsg::VerifyMembership(msg) => { + let ctx = Context::::new_ro(deps, env); + let msg = VerifyMembershipMsg::try_from(msg)?; + let consensus_state = ctx + .consensus_state(&client_id, msg.height) + .map_err(|e| ContractError::Grandpa(e.to_string()))?; + verify_membership::( + &msg.prefix, + &msg.proof, + &consensus_state.root, + msg.path, + msg.value, + ) + .map_err(|e| ContractError::Grandpa(e.to_string()))?; + to_binary(&QueryResponse::success()) + }, + QueryMsg::VerifyNonMembership(msg) => { + let ctx = Context::::new_ro(deps, env); + let msg = VerifyNonMembershipMsg::try_from(msg)?; + let consensus_state = ctx + .consensus_state(&client_id, msg.height) + .map_err(|e| ContractError::Grandpa(e.to_string()))?; + + verify_non_membership::( + &msg.prefix, + &msg.proof, + &consensus_state.root, + msg.path, + ) + .map_err(|e| ContractError::Grandpa(e.to_string())) + .map(|_| to_binary(&QueryResponse::success()))? + }, } } @@ -405,15 +406,18 @@ where H: grandpa_light_client_primitives::HostFunctions
, { let height = client_state.latest_height(); + let mut heights: Vec = vec![]; match consensus_update { ConsensusUpdateResult::Single(cs) => { log!(ctx, "Storing consensus state: {:?}", height); + heights.push(height); ctx.store_consensus_state(client_id.clone(), height, cs) .map_err(|e| ContractError::Grandpa(e.to_string()))?; }, ConsensusUpdateResult::Batch(css) => for (height, cs) in css { log!(ctx, "Storing consensus state: {:?}", height); + heights.push(height); ctx.store_consensus_state(client_id.clone(), height, cs) .map_err(|e| ContractError::Grandpa(e.to_string()))?; }, @@ -421,7 +425,7 @@ where log!(ctx, "Storing client state with height: {:?}", height); ctx.store_client_state(client_id, client_state) .map_err(|e| ContractError::Grandpa(e.to_string()))?; - Ok(to_binary(&ContractResult::success())) + Ok(to_binary(&ContractResult::success().heights(heights))) } // The FFIs below are required because of sp-io dependency that expects the functions to be diff --git a/light-clients/ics10-grandpa-cw/src/error.rs b/light-clients/ics10-grandpa-cw/src/error.rs index cefc3c7a6..44d4baf7e 100644 --- a/light-clients/ics10-grandpa-cw/src/error.rs +++ b/light-clients/ics10-grandpa-cw/src/error.rs @@ -55,3 +55,9 @@ impl From for ContractError { ContractError::Grandpa(e.to_string()) } } + +impl From for StdError { + fn from(e: ContractError) -> Self { + StdError::GenericErr { msg: e.to_string() } + } +} \ No newline at end of file diff --git a/light-clients/ics10-grandpa-cw/src/helpers.rs b/light-clients/ics10-grandpa-cw/src/helpers.rs index 097b925fa..684306031 100644 --- a/light-clients/ics10-grandpa-cw/src/helpers.rs +++ b/light-clients/ics10-grandpa-cw/src/helpers.rs @@ -18,7 +18,7 @@ use serde::{Deserialize, Serialize}; use cosmwasm_std::{to_binary, Addr, CosmosMsg, StdResult, WasmMsg}; -use crate::msg::ExecuteMsg; +use crate::msg::SudoMsg; /// CwTemplateContract is a wrapper around Addr that provides a lot of helpers /// for working with this. @@ -30,7 +30,7 @@ impl CwTemplateContract { self.0.clone() } - pub fn call>(&self, msg: T) -> StdResult { + pub fn call>(&self, msg: T) -> StdResult { let msg = to_binary(&msg.into())?; Ok(WasmMsg::Execute { contract_addr: self.addr().into(), msg, funds: vec![] }.into()) } diff --git a/light-clients/ics10-grandpa-cw/src/msg.rs b/light-clients/ics10-grandpa-cw/src/msg.rs index b90433c17..db3ed6222 100644 --- a/light-clients/ics10-grandpa-cw/src/msg.rs +++ b/light-clients/ics10-grandpa-cw/src/msg.rs @@ -26,11 +26,11 @@ use ibc::{ }; use ibc_proto::{google::protobuf::Any, ibc::core::client::v1::Height as HeightRaw}; use ics08_wasm::{ - client_message::Header as WasmHeader, client_state::ClientState as WasmClientState, + client_state::ClientState as WasmClientState, consensus_state::ConsensusState as WasmConsensusState, }; use ics10_grandpa::{ - client_message::{ClientMessage, Header, Misbehaviour}, + client_message::{ClientMessage, Header, Misbehaviour, GRANDPA_HEADER_TYPE_URL, GRANDPA_MISBEHAVIOUR_TYPE_URL}, client_state::ClientState, consensus_state::ConsensusState, }; @@ -57,18 +57,40 @@ pub struct GenesisMetadata { #[cw_serde] pub struct QueryResponse { - pub status: String, + pub is_valid: bool, + #[serde(skip_serializing_if = "Option::is_none")] + pub status: Option, #[serde(skip_serializing_if = "Option::is_none")] pub genesis_metadata: Option>, + #[serde(skip_serializing_if = "Option::is_none")] + pub found_misbehaviour: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub timestamp: Option, } impl QueryResponse { - pub fn status(status: String) -> Self { - Self { status, genesis_metadata: None } + pub fn success() -> Self { + Self { is_valid: true, status: None, genesis_metadata: None, found_misbehaviour: None, timestamp: None } + } + + pub fn status(mut self, status: String) -> Self { + self.status = Some(status); + self + } + + pub fn genesis_metadata(mut self, genesis_metadata: Option>) -> Self { + self.genesis_metadata = genesis_metadata; + self + } + + pub fn misbehaviour(mut self, found_misbehavior: bool) -> Self { + self.found_misbehaviour = Some(found_misbehavior); + self } - pub fn genesis_metadata(genesis_metadata: Option>) -> Self { - Self { status: "".to_string(), genesis_metadata } + pub fn timestamp(mut self, timestamp: u64) -> Self { + self.timestamp = Some(timestamp); + self } } @@ -78,25 +100,26 @@ pub struct ContractResult { pub error_msg: String, #[serde(skip_serializing_if = "Option::is_none")] pub data: Option>, - pub found_misbehaviour: bool, + #[serde(skip_serializing_if = "Option::is_none")] + pub heights: Option>, } impl ContractResult { pub fn success() -> Self { - Self { is_valid: true, error_msg: "".to_string(), data: None, found_misbehaviour: false } + Self { is_valid: true, error_msg: "".to_string(), data: None, heights: None } } pub fn error(msg: String) -> Self { - Self { is_valid: false, error_msg: msg, data: None, found_misbehaviour: false } + Self { is_valid: false, error_msg: msg, data: None, heights: None } } - pub fn misbehaviour(mut self, found: bool) -> Self { - self.found_misbehaviour = found; + pub fn data(mut self, data: Vec) -> Self { + self.data = Some(data); self } - pub fn data(mut self, data: Vec) -> Self { - self.data = Some(data); + pub fn heights(mut self, heights: Vec) -> Self { + self.heights = Some(heights); self } } @@ -121,25 +144,29 @@ pub struct ClientCreateRequest { } #[cw_serde] -pub enum ExecuteMsg { - InitializeState(InitializeState), - ClientCreateRequest(WasmClientState), - VerifyMembership(VerifyMembershipMsgRaw), - VerifyNonMembership(VerifyNonMembershipMsgRaw), - VerifyClientMessage(VerifyClientMessageRaw), - CheckForMisbehaviour(CheckForMisbehaviourMsgRaw), +pub enum SudoMsg { + CheckSubstituteAndUpdateState(CheckSubstituteAndUpdateStateMsgRaw), UpdateStateOnMisbehaviour(UpdateStateOnMisbehaviourMsgRaw), UpdateState(UpdateStateMsgRaw), - CheckSubstituteAndUpdateState(CheckSubstituteAndUpdateStateMsgRaw), VerifyUpgradeAndUpdateState(VerifyUpgradeAndUpdateStateMsgRaw), } #[cw_serde] pub enum QueryMsg { + CheckForMisbehaviour(CheckForMisbehaviourMsgRaw), ClientTypeMsg(ClientTypeMsg), GetLatestHeightsMsg(GetLatestHeightsMsg), ExportMetadata(ExportMetadataMsg), Status(StatusMsg), + TimestampAtHeight(TimestampAtHeightMsg), + VerifyMembership(VerifyMembershipMsgRaw), + VerifyNonMembership(VerifyNonMembershipMsgRaw), + VerifyClientMessage(VerifyClientMessageRaw), +} + +#[cw_serde] +pub struct TimestampAtHeightMsg { + pub height: Height, } #[cw_serde] @@ -232,18 +259,12 @@ impl TryFrom for VerifyNonMembershipMsg { } #[cw_serde] -pub struct WasmMisbehaviour { +pub struct ClientMessageRaw { #[schemars(with = "String")] #[serde(with = "Base64", default)] pub data: Bytes, } -#[cw_serde] -pub enum ClientMessageRaw { - Header(WasmHeader), - Misbehaviour(WasmMisbehaviour), -} - #[cw_serde] pub struct VerifyClientMessageRaw { pub client_message: ClientMessageRaw, @@ -264,15 +285,11 @@ impl TryFrom for VerifyClientMessage { impl VerifyClientMessage { fn decode_client_message(raw: ClientMessageRaw) -> Result { - let client_message = match raw { - ClientMessageRaw::Header(header) => { - let any = Any::decode(&mut header.data.as_slice())?; - ClientMessage::Header(Header::decode_vec(&any.value)?) - }, - ClientMessageRaw::Misbehaviour(misbehaviour) => { - let any = Any::decode(&mut misbehaviour.data.as_slice())?; - ClientMessage::Misbehaviour(Misbehaviour::decode_vec(&any.value)?) - }, + let any = Any::decode(raw.data.as_slice())?; + let client_message = match &*any.type_url { + GRANDPA_HEADER_TYPE_URL => ClientMessage::Header(Header::decode_vec(&any.value)?), + GRANDPA_MISBEHAVIOUR_TYPE_URL => ClientMessage::Misbehaviour(Misbehaviour::decode_vec(&any.value)?), + _ => return Err(ContractError::Grandpa("unknown client message type".to_string())), }; Ok(client_message) } From eb6cfbabd1c836c5f01dc173b96c6cdab33fe3c4 Mon Sep 17 00:00:00 2001 From: Steve Miskovetz Date: Fri, 18 Aug 2023 12:13:42 -0600 Subject: [PATCH 10/37] Get hypserspace to build --- contracts/pallet-ibc/src/light_clients.rs | 67 +++++-------------- hyperspace/core/src/substrate/macros.rs | 2 +- .../ics08-wasm/src/client_message.rs | 2 - light-clients/ics08-wasm/src/instantiate.rs | 1 + 4 files changed, 18 insertions(+), 54 deletions(-) diff --git a/contracts/pallet-ibc/src/light_clients.rs b/contracts/pallet-ibc/src/light_clients.rs index fdf99403c..d9cb48ee5 100644 --- a/contracts/pallet-ibc/src/light_clients.rs +++ b/contracts/pallet-ibc/src/light_clients.rs @@ -25,9 +25,7 @@ use ics07_tendermint::{ consensus_state::TENDERMINT_CONSENSUS_STATE_TYPE_URL, }; use ics08_wasm::{ - client_message::{ - WASM_CLIENT_MESSAGE_TYPE_URL, WASM_HEADER_TYPE_URL, WASM_MISBEHAVIOUR_TYPE_URL, - }, + client_message::WASM_CLIENT_MESSAGE_TYPE_URL, client_state::WASM_CLIENT_STATE_TYPE_URL, consensus_state::WASM_CONSENSUS_STATE_TYPE_URL, Bytes, @@ -348,11 +346,8 @@ impl AnyClientMessage { ics10_grandpa::client_message::ClientMessage::Header(h) => Some(h.height()), ics10_grandpa::client_message::ClientMessage::Misbehaviour(_) => None, }, - Self::Wasm(inner) => match inner { - ics08_wasm::client_message::ClientMessage::Header(h) => - h.inner.maybe_header_height(), - ics08_wasm::client_message::ClientMessage::Misbehaviour(_) => None, - }, + Self::Wasm(inner) => + inner.inner.maybe_header_height(), #[cfg(test)] Self::Mock(inner) => match inner { ibc::mock::header::MockClientMessage::Header(h) => Some(h.height()), @@ -362,40 +357,26 @@ impl AnyClientMessage { } pub fn wasm(inner: Self) -> Result { - let maybe_height = inner.maybe_header_height(); - Ok(match maybe_height { - Some(height) => Self::Wasm(ics08_wasm::client_message::ClientMessage::Header( - ics08_wasm::client_message::Header { - data: inner.encode_to_vec()?, - height, - inner: Box::new(inner), - }, - )), - None => Self::Wasm(ics08_wasm::client_message::ClientMessage::Misbehaviour( - ics08_wasm::client_message::Misbehaviour { - data: inner.encode_to_vec()?, - inner: Box::new(inner), - }, - )), - }) + Ok(Self::Wasm( + ics08_wasm::client_message::ClientMessage { + data: inner.encode_to_vec()?, + inner: Box::new(inner), + } + )) } pub fn unpack_recursive(&self) -> &Self { match self { - Self::Wasm(ics08_wasm::client_message::ClientMessage::Header(h)) => - h.inner.unpack_recursive(), - Self::Wasm(ics08_wasm::client_message::ClientMessage::Misbehaviour(m)) => - m.inner.unpack_recursive(), + Self::Wasm(ics08_wasm::client_message::ClientMessage{inner, data}) => + inner.unpack_recursive(), _ => self, } } pub fn unpack_recursive_into(self) -> Self { match self { - Self::Wasm(ics08_wasm::client_message::ClientMessage::Header(h)) => - h.inner.unpack_recursive_into(), - Self::Wasm(ics08_wasm::client_message::ClientMessage::Misbehaviour(m)) => - m.inner.unpack_recursive_into(), + Self::Wasm(ics08_wasm::client_message::ClientMessage{inner, data}) => + inner.unpack_recursive_into(), _ => self, } } @@ -445,16 +426,6 @@ impl TryFrom for AnyClientMessage { ics08_wasm::client_message::ClientMessage::decode_vec(&value.value) .map_err(ics02_client::error::Error::decode_raw_header)?, )), - WASM_HEADER_TYPE_URL => - Ok(Self::Wasm(ics08_wasm::client_message::ClientMessage::Header( - ics08_wasm::client_message::Header::decode_vec(&value.value) - .map_err(ics02_client::error::Error::decode_raw_header)?, - ))), - WASM_MISBEHAVIOUR_TYPE_URL => - Ok(Self::Wasm(ics08_wasm::client_message::ClientMessage::Misbehaviour( - ics08_wasm::client_message::Misbehaviour::decode_vec(&value.value) - .map_err(ics02_client::error::Error::decode_raw_header)?, - ))), _ => Err(ics02_client::error::Error::unknown_consensus_state_type(value.type_url)), } } @@ -463,15 +434,9 @@ impl TryFrom for AnyClientMessage { impl From for Any { fn from(client_msg: AnyClientMessage) -> Self { match client_msg { - AnyClientMessage::Wasm(msg) => match msg { - ics08_wasm::client_message::ClientMessage::Header(h) => Any { - type_url: WASM_HEADER_TYPE_URL.to_string(), - value: h.encode_vec().expect("encode_vec failed"), - }, - ics08_wasm::client_message::ClientMessage::Misbehaviour(m) => Any { - type_url: WASM_MISBEHAVIOUR_TYPE_URL.to_string(), - value: m.encode_vec().expect("encode_vec failed"), - }, + AnyClientMessage::Wasm(msg) => Any { + type_url: WASM_CLIENT_MESSAGE_TYPE_URL.to_string(), + value: msg.encode_vec().expect("encode_vec failed") }, AnyClientMessage::Grandpa(msg) => match msg { ics10_grandpa::client_message::ClientMessage::Header(h) => Any { diff --git a/hyperspace/core/src/substrate/macros.rs b/hyperspace/core/src/substrate/macros.rs index aed1b79b5..a2d960e84 100644 --- a/hyperspace/core/src/substrate/macros.rs +++ b/hyperspace/core/src/substrate/macros.rs @@ -487,7 +487,7 @@ macro_rules! define_ibc_event_wrapper { RawIbcEvent::AppModule { kind, module_id }, MetadataIbcEvent::Empty => RawIbcEvent::Empty, MetadataIbcEvent::ChainError => RawIbcEvent::ChainError, - MetadataIbcEvent::PushWasmCode{ wasm_code_hash } => RawIbcEvent::PushWasmCode { + MetadataIbcEvent::PushWasmCode{ wasm_code_id: wasm_code_hash } => RawIbcEvent::PushWasmCode { wasm_code_hash }, $($additional)* diff --git a/light-clients/ics08-wasm/src/client_message.rs b/light-clients/ics08-wasm/src/client_message.rs index d94b04321..b7ee22ec5 100644 --- a/light-clients/ics08-wasm/src/client_message.rs +++ b/light-clients/ics08-wasm/src/client_message.rs @@ -13,7 +13,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -#[cfg(feature = "cosmwasm")] use crate::Bytes; use alloc::{ boxed::Box, @@ -21,7 +20,6 @@ use alloc::{ vec::Vec, }; use core::fmt::Display; -#[cfg(feature = "cosmwasm")] use ibc::{ core::ics02_client::{client_message::ClientMessage as IbcClientMessage, error::Error}, protobuf::Protobuf, diff --git a/light-clients/ics08-wasm/src/instantiate.rs b/light-clients/ics08-wasm/src/instantiate.rs index 4e8bad55c..a06f1237d 100644 --- a/light-clients/ics08-wasm/src/instantiate.rs +++ b/light-clients/ics08-wasm/src/instantiate.rs @@ -1,5 +1,6 @@ use super::client_state::ClientState; use crate::consensus_state::ConsensusState; +#[cfg(feature = "cosmwasm")] use cosmwasm_schema::cw_serde; #[cfg_attr(feature = "cosmwasm", cw_serde)] From d5ec64536e72a043f3c6dacf7cf2cbf9b219fedc Mon Sep 17 00:00:00 2001 From: Steve Miskovetz Date: Tue, 22 Aug 2023 15:04:29 -0600 Subject: [PATCH 11/37] E2e wip --- contracts/pallet-ibc/src/light_clients.rs | 42 ++++------------------- hyperspace/primitives/src/lib.rs | 2 +- scripts/build-parachain-node-docker.sh | 2 +- 3 files changed, 9 insertions(+), 37 deletions(-) diff --git a/contracts/pallet-ibc/src/light_clients.rs b/contracts/pallet-ibc/src/light_clients.rs index d9cb48ee5..376886501 100644 --- a/contracts/pallet-ibc/src/light_clients.rs +++ b/contracts/pallet-ibc/src/light_clients.rs @@ -3,15 +3,12 @@ use frame_support::{ pallet_prelude::{StorageValue, ValueQuery}, traits::StorageInstance, }; -use ibc::{ - core::{ - ics02_client, - ics02_client::{ - client_consensus::ConsensusState, client_message::ClientMessage, - client_state::ClientState, - }, +use ibc::core::{ + ics02_client, + ics02_client::{ + client_consensus::ConsensusState, client_message::ClientMessage, + client_state::ClientState, }, - Height, }; use ibc_derive::{ClientDef, ClientMessage, ClientState, ConsensusState, Protobuf}; use ibc_primitives::runtime_interface; @@ -331,31 +328,6 @@ pub enum AnyClientMessage { } impl AnyClientMessage { - pub fn maybe_header_height(&self) -> Option { - match self { - Self::Tendermint(inner) => match inner { - ics07_tendermint::client_message::ClientMessage::Header(h) => Some(h.height()), - ics07_tendermint::client_message::ClientMessage::Misbehaviour(_) => None, - }, - Self::Beefy(inner) => match inner { - ics11_beefy::client_message::ClientMessage::Header(_) => - unimplemented!("beefy header height"), - ics11_beefy::client_message::ClientMessage::Misbehaviour(_) => None, - }, - Self::Grandpa(inner) => match inner { - ics10_grandpa::client_message::ClientMessage::Header(h) => Some(h.height()), - ics10_grandpa::client_message::ClientMessage::Misbehaviour(_) => None, - }, - Self::Wasm(inner) => - inner.inner.maybe_header_height(), - #[cfg(test)] - Self::Mock(inner) => match inner { - ibc::mock::header::MockClientMessage::Header(h) => Some(h.height()), - ibc::mock::header::MockClientMessage::Misbehaviour(_) => None, - }, - } - } - pub fn wasm(inner: Self) -> Result { Ok(Self::Wasm( ics08_wasm::client_message::ClientMessage { @@ -368,7 +340,7 @@ impl AnyClientMessage { pub fn unpack_recursive(&self) -> &Self { match self { Self::Wasm(ics08_wasm::client_message::ClientMessage{inner, data}) => - inner.unpack_recursive(), + &**inner, _ => self, } } @@ -376,7 +348,7 @@ impl AnyClientMessage { pub fn unpack_recursive_into(self) -> Self { match self { Self::Wasm(ics08_wasm::client_message::ClientMessage{inner, data}) => - inner.unpack_recursive_into(), + *inner, _ => self, } } diff --git a/hyperspace/primitives/src/lib.rs b/hyperspace/primitives/src/lib.rs index 9b4b4ad8c..6acaa5a51 100644 --- a/hyperspace/primitives/src/lib.rs +++ b/hyperspace/primitives/src/lib.rs @@ -100,7 +100,7 @@ fn default_skip_optional_client_updates() -> bool { } fn max_packets_to_process() -> u32 { - 50 + 150 } // TODO: move other fields like `client_id`, `connection_id`, etc. here diff --git a/scripts/build-parachain-node-docker.sh b/scripts/build-parachain-node-docker.sh index 4594a4e7a..655808d09 100755 --- a/scripts/build-parachain-node-docker.sh +++ b/scripts/build-parachain-node-docker.sh @@ -3,4 +3,4 @@ set -e set -x -DOCKER_BUILDKIT=0 docker build --platform linux/amd64 -f scripts/parachain.Dockerfile . -t parachain-node:latest \ No newline at end of file +DOCKER_BUILDKIT=0 docker build --platform linux/amd64 -f scripts/parachain.Dockerfile . -t parachain-node:localv39 From fce2d6303cc111c8b5f2aa47b2fba3dc61a79bf2 Mon Sep 17 00:00:00 2001 From: Steve Miskovetz Date: Wed, 30 Aug 2023 12:11:51 -0600 Subject: [PATCH 12/37] Update client message --- contracts/pallet-ibc/src/light_clients.rs | 8 -- light-clients/ics08-wasm/src/client_def.rs | 8 +- .../ics08-wasm/src/client_message.rs | 86 +++++++++++-------- light-clients/ics10-grandpa-cw/src/client.rs | 33 ------- 4 files changed, 54 insertions(+), 81 deletions(-) diff --git a/contracts/pallet-ibc/src/light_clients.rs b/contracts/pallet-ibc/src/light_clients.rs index 376886501..81da8be9f 100644 --- a/contracts/pallet-ibc/src/light_clients.rs +++ b/contracts/pallet-ibc/src/light_clients.rs @@ -337,14 +337,6 @@ impl AnyClientMessage { )) } - pub fn unpack_recursive(&self) -> &Self { - match self { - Self::Wasm(ics08_wasm::client_message::ClientMessage{inner, data}) => - &**inner, - _ => self, - } - } - pub fn unpack_recursive_into(self) -> Self { match self { Self::Wasm(ics08_wasm::client_message::ClientMessage{inner, data}) => diff --git a/light-clients/ics08-wasm/src/client_def.rs b/light-clients/ics08-wasm/src/client_def.rs index e687273f1..3f37fc96b 100644 --- a/light-clients/ics08-wasm/src/client_def.rs +++ b/light-clients/ics08-wasm/src/client_def.rs @@ -81,7 +81,7 @@ where ctx, client_id, *client_state.inner, - client_msg.into_inner(), + *client_msg.inner, ) } @@ -96,7 +96,7 @@ where ctx, client_id, *client_state.inner, - client_msg.into_inner(), + *client_msg.inner, )?; let client_state = ClientState { data: client_state.data.clone(), @@ -115,7 +115,7 @@ where ) -> Result { let inner_client_state = self .inner - .update_state_on_misbehaviour(*client_state.inner, client_msg.into_inner())?; + .update_state_on_misbehaviour(*client_state.inner, *client_msg.inner)?; Ok(ClientState { data: client_state.data.clone(), code_hash: client_state.code_hash.clone(), @@ -136,7 +136,7 @@ where ctx, client_id, *client_state.inner, - client_msg.into_inner(), + *client_msg.inner, ) } diff --git a/light-clients/ics08-wasm/src/client_message.rs b/light-clients/ics08-wasm/src/client_message.rs index b7ee22ec5..742086389 100644 --- a/light-clients/ics08-wasm/src/client_message.rs +++ b/light-clients/ics08-wasm/src/client_message.rs @@ -12,38 +12,43 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. - +#[cfg(feature = "cosmwasm")] +use crate::msg::Base64; use crate::Bytes; use alloc::{ boxed::Box, - string::ToString, + string::{String, ToString}, vec::Vec, }; -use core::fmt::Display; +use core::{ + convert::Infallible, + fmt::{Debug, Display}, +}; +#[cfg(feature = "cosmwasm")] +use cosmwasm_schema::cw_serde; use ibc::{ core::ics02_client::{client_message::ClientMessage as IbcClientMessage, error::Error}, protobuf::Protobuf, }; use ibc_proto::google::protobuf::Any; +use ibc_proto::ibc::lightclients::wasm::v1::ClientMessage as RawClientMessage; +use prost::Message; pub const WASM_CLIENT_MESSAGE_TYPE_URL: &str = "/ibc.lightclients.wasm.v1.ClientMessage"; -#[derive(Clone, Debug, PartialEq, Eq)] +//#[derive(Clone, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "cosmwasm", cw_serde)] +#[cfg_attr(not(feature = "cosmwasm"), derive(Clone, Debug, PartialEq))] +#[derive(Eq)] pub struct ClientMessage { + #[cfg_attr(feature = "cosmwasm", serde(skip))] + #[cfg_attr(feature = "cosmwasm", schemars(skip))] pub inner: Box, + #[cfg_attr(feature = "cosmwasm", schemars(with = "String"))] + #[cfg_attr(feature = "cosmwasm", serde(with = "Base64", default))] pub data: Bytes, } -impl ClientMessage { - pub fn inner(&self) -> &AnyClientMessage { - &self.inner - } - - pub fn into_inner(self) -> AnyClientMessage { - *self.inner - } -} - impl IbcClientMessage for ClientMessage where AnyClientMessage: IbcClientMessage, @@ -55,43 +60,52 @@ where } } -impl Protobuf for ClientMessage +impl ClientMessage where AnyClientMessage: Clone, - AnyClientMessage: TryFrom, + AnyClientMessage: TryFrom + IbcClientMessage, >::Error: Display, { + pub fn to_any(&self) -> Any { + Any { + value: self.encode_vec().expect("encode client message"), + type_url: WASM_CLIENT_MESSAGE_TYPE_URL.to_string(), + } + } } -impl TryFrom for ClientMessage +impl TryFrom for ClientMessage where - AnyClientMessage: Clone, - AnyClientMessage: TryFrom, + AnyClientMessage: Clone + TryFrom, >::Error: Display, { - type Error = Error; + type Error = String; - fn try_from(any: Any) -> Result { - let msg = match &*any.type_url { - WASM_CLIENT_MESSAGE_TYPE_URL => - ClientMessage::decode(&*any.value).map_err(|e| Error::decode_raw_header(e))?, - _ => return Err(Error::malformed_header()), // TODO: choose a better error - }; + fn try_from(raw: RawClientMessage) -> Result { + let any = Any::decode(&mut &raw.data[..]) + .map_err(|e| format!("failed to decode ClientMessage::data into Any: {}", e))?; + let inner = AnyClientMessage::try_from(any).map_err( + |e| { + format!("failed to decode ClientMessage::data into ClientMessage: {}", e) + })?; + Ok(Self { data: raw.data, inner: Box::new(inner)}) - Ok(msg) } } -impl From> for Any +impl From> + for RawClientMessage +{ + fn from(value: ClientMessage) -> Self { + Self { data: value.data } + } +} + +impl Protobuf for ClientMessage where - AnyClientMessage: Clone, - AnyClientMessage: TryFrom, + AnyClientMessage: Clone + IbcClientMessage + TryFrom, >::Error: Display, { - fn from(msg: ClientMessage) -> Self { - Any { - value: msg.encode_vec().expect("encode client message"), - type_url: WASM_CLIENT_MESSAGE_TYPE_URL.to_string(), - } - } } + + diff --git a/light-clients/ics10-grandpa-cw/src/client.rs b/light-clients/ics10-grandpa-cw/src/client.rs index cbf9dc150..d7cbca1dd 100644 --- a/light-clients/ics10-grandpa-cw/src/client.rs +++ b/light-clients/ics10-grandpa-cw/src/client.rs @@ -56,11 +56,8 @@ impl<'a, H: HostFunctions
> ClientTypes for Context<'a impl<'a, H: HostFunctions
> ClientReader for Context<'a, H> { fn client_type(&self, client_id: &ClientId) -> Result { - log!(self, "in client : [client_type] >> client_id = {:?}", client_id); - let clients = ReadonlyClients::new(self.storage()); if !clients.contains_key(client_id) { - log!(self, "in client : [client_type] >> read client_type is None"); return Err(Error::client_not_found(client_id.clone())) } @@ -76,18 +73,15 @@ impl<'a, H: HostFunctions
> ClientReader for Context<' match ClientType::from_str(&data) { Err(_err) => Err(Error::unknown_client_type(data.to_string())), Ok(val) => { - log!(self, "in client : [client_type] >> client_type : {:?}", val); Ok(val) }, } } fn client_state(&self, client_id: &ClientId) -> Result, Error> { - log!(self, "in client : [client_state] >> client_id = {:?}", client_id); let client_states = ReadonlyClientStates::new(self.storage()); let data = client_states.get().ok_or_else(|| Error::client_not_found(client_id.clone()))?; let state = Self::decode_client_state(&data)?; - log!(self, "in client : [client_state] >> any client_state: {:?}", state); Ok(state) } @@ -96,23 +90,12 @@ impl<'a, H: HostFunctions
> ClientReader for Context<' client_id: &ClientId, height: Height, ) -> Result { - log!(self, "in client : [consensus_state] >> height = {:?}", height); let consensus_states = ReadonlyConsensusStates::new(self.storage()); let value = consensus_states .get(height) .ok_or_else(|| Error::consensus_state_not_found(client_id.clone(), height))?; - log!( - self, - "in client : [consensus_state] >> consensus_state (raw): {}", - hex::encode(&value) - ); let any_consensus_state = Self::decode_consensus_state(&value)?; - log!( - self, - "in client : [consensus_state] >> any consensus state = {:?}", - any_consensus_state - ); Ok(any_consensus_state) } @@ -150,7 +133,6 @@ impl<'a, H: HostFunctions
> ClientReader for Context<' } fn host_height(&self) -> Height { - log!(self, "in client: [host_height]"); Height::new(self.env.block.height, 0) } @@ -177,7 +159,6 @@ impl<'a, H: HostFunctions
> ClientReader for Context<' fn client_counter(&self) -> Result { let count = CLIENT_COUNTER.load(self.storage()).unwrap_or_default(); - log!(self, "in client : [client_counter] >> client_counter: {:?}", count); Ok(count as u64) } } @@ -196,7 +177,6 @@ impl<'a, H: HostFunctions
> ClientKeeper for Context<' client_id: ClientId, client_state: Self::AnyClientState, ) -> Result<(), Error> { - log!(self, "in client : [store_client_state]"); let client_states = ReadonlyClientStates::new(self.storage()); // let data = client_states.get().ok_or_else(|| // Error::client_not_found(client_id.clone()))?; @@ -223,7 +203,6 @@ impl<'a, H: HostFunctions
> ClientKeeper for Context<' }; let vec1 = Self::encode_client_state(client_state, code_hash)?; - log!(self, "in cliden : [store_client_state] >> wasm client state (raw)"); let mut client_state_storage = ClientStates::new(self.storage_mut()); client_state_storage.insert(vec1); Ok(()) @@ -235,19 +214,7 @@ impl<'a, H: HostFunctions
> ClientKeeper for Context<' height: Height, consensus_state: Self::AnyConsensusState, ) -> Result<(), Error> { - log!( - self, - "in client : [store_consensus_state] >> client_id = {:?}, height = {:?}", - client_id, - height, - ); - let encoded = Self::encode_consensus_state(consensus_state); - log!( - self, - "in client : [store_consensus_state] >> wasm consensus state (raw) = {}", - hex::encode(&encoded) - ); let mut consensus_states = ConsensusStates::new(self.storage_mut()); consensus_states.insert(height, encoded); Ok(()) From 4b2fa708ecb09e5a24512abf5d61d72eb0d4c171 Mon Sep 17 00:00:00 2001 From: Steve Miskovetz Date: Wed, 13 Sep 2023 17:04:18 -0600 Subject: [PATCH 13/37] Revert parachain version --- scripts/build-parachain-node-docker.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build-parachain-node-docker.sh b/scripts/build-parachain-node-docker.sh index 655808d09..d3da02a24 100755 --- a/scripts/build-parachain-node-docker.sh +++ b/scripts/build-parachain-node-docker.sh @@ -3,4 +3,4 @@ set -e set -x -DOCKER_BUILDKIT=0 docker build --platform linux/amd64 -f scripts/parachain.Dockerfile . -t parachain-node:localv39 +DOCKER_BUILDKIT=0 docker build --platform linux/amd64 -f scripts/parachain.Dockerfile . -t parachain-node:latest From 3de0e2a5733f06e2f74ffd8f7a34c3532984d67b Mon Sep 17 00:00:00 2001 From: Steve Miskovetz Date: Tue, 3 Oct 2023 12:27:23 -0600 Subject: [PATCH 14/37] Add parachain user to parachain docker file --- scripts/parachain.Dockerfile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/parachain.Dockerfile b/scripts/parachain.Dockerfile index 60b3f63b3..de9eae565 100644 --- a/scripts/parachain.Dockerfile +++ b/scripts/parachain.Dockerfile @@ -29,6 +29,11 @@ RUN apt update && \ update-ca-certificates && \ rm -rf /var/lib/apt/lists/* +RUN useradd -m -u 1000 -U -s /bin/sh -d /parachain parachain && \ + chown -R parachain:parachain /usr/local/bin + +USER parachain + # check if executable works in this container RUN /usr/local/bin/parachain-node --version From 6f36ad20f75faeb0cb5d784354db867c85bd3205 Mon Sep 17 00:00:00 2001 From: Carlos Rodriguez Date: Wed, 4 Oct 2023 11:53:51 +0200 Subject: [PATCH 15/37] imp: remove unused fields in contract result --- light-clients/ics07-tendermint-cw/src/msg.rs | 13 ++----------- light-clients/ics10-grandpa-cw/src/msg.rs | 13 ++----------- 2 files changed, 4 insertions(+), 22 deletions(-) diff --git a/light-clients/ics07-tendermint-cw/src/msg.rs b/light-clients/ics07-tendermint-cw/src/msg.rs index f5572a262..7497ae173 100644 --- a/light-clients/ics07-tendermint-cw/src/msg.rs +++ b/light-clients/ics07-tendermint-cw/src/msg.rs @@ -96,26 +96,17 @@ impl QueryResponse { #[cw_serde] pub struct ContractResult { - pub is_valid: bool, - pub error_msg: String, - #[serde(skip_serializing_if = "Option::is_none")] - pub data: Option>, #[serde(skip_serializing_if = "Option::is_none")] pub heights: Option>, } impl ContractResult { pub fn success() -> Self { - Self { is_valid: true, error_msg: "".to_string(), data: None, heights: None } + Self { heights: None } } pub fn error(msg: String) -> Self { - Self { is_valid: false, error_msg: msg, data: None, heights: None } - } - - pub fn data(mut self, data: Vec) -> Self { - self.data = Some(data); - self + Self { heights: None } } pub fn heights(mut self, heights: Vec) -> Self { diff --git a/light-clients/ics10-grandpa-cw/src/msg.rs b/light-clients/ics10-grandpa-cw/src/msg.rs index db3ed6222..23d61eb51 100644 --- a/light-clients/ics10-grandpa-cw/src/msg.rs +++ b/light-clients/ics10-grandpa-cw/src/msg.rs @@ -96,26 +96,17 @@ impl QueryResponse { #[cw_serde] pub struct ContractResult { - pub is_valid: bool, - pub error_msg: String, - #[serde(skip_serializing_if = "Option::is_none")] - pub data: Option>, #[serde(skip_serializing_if = "Option::is_none")] pub heights: Option>, } impl ContractResult { pub fn success() -> Self { - Self { is_valid: true, error_msg: "".to_string(), data: None, heights: None } + Self { heights: None } } pub fn error(msg: String) -> Self { - Self { is_valid: false, error_msg: msg, data: None, heights: None } - } - - pub fn data(mut self, data: Vec) -> Self { - self.data = Some(data); - self + Self { heights: None } } pub fn heights(mut self, heights: Vec) -> Self { From 7bae68e3e503acbf1c226440d3550c397985fc88 Mon Sep 17 00:00:00 2001 From: Carlos Rodriguez Date: Wed, 4 Oct 2023 22:27:02 +0200 Subject: [PATCH 16/37] fix: make verify (non) membership sudo calls --- .../ics07-tendermint-cw/src/contract.rs | 86 +++++---- light-clients/ics07-tendermint-cw/src/msg.rs | 174 +++++++++--------- .../ics10-grandpa-cw/src/contract.rs | 62 +++---- light-clients/ics10-grandpa-cw/src/msg.rs | 147 ++++++++------- 4 files changed, 232 insertions(+), 237 deletions(-) diff --git a/light-clients/ics07-tendermint-cw/src/contract.rs b/light-clients/ics07-tendermint-cw/src/contract.rs index 3aab249f9..61fd4217b 100644 --- a/light-clients/ics07-tendermint-cw/src/contract.rs +++ b/light-clients/ics07-tendermint-cw/src/contract.rs @@ -248,6 +248,48 @@ fn process_message( .map_err(|e| ContractError::Tendermint(e.to_string()))?; Ok(to_binary(&ContractResult::success())) }), + SudoMsg::VerifyMembership(msg) => { + let client_state = ctx + .client_state(&client_id) + .map_err(|e| ContractError::Tendermint(e.to_string()))?; + let msg = VerifyMembershipMsg::try_from(msg)?; + verify_delay_passed(&ctx, msg.height, msg.delay_time_period, msg.delay_block_period) + .map_err(|e| ContractError::Tendermint(e.to_string()))?; + let consensus_state = ctx + .consensus_state(&client_id, msg.height) + .map_err(|e| ContractError::Tendermint(e.to_string()))?; + verify_membership::( + &client_state, + &msg.prefix, + &msg.proof, + &consensus_state.root, + msg.path, + msg.value, + ) + .map_err(|e| ContractError::Tendermint(e.to_string())) + .map(|_| to_binary(&QueryResponse::success())) + }, + SudoMsg::VerifyNonMembership(msg) => { + let client_state = ctx + .client_state(&client_id) + .map_err(|e| ContractError::Tendermint(e.to_string()))?; + let msg = VerifyNonMembershipMsg::try_from(msg)?; + verify_delay_passed(&ctx, msg.height, msg.delay_time_period, msg.delay_block_period) + .map_err(|e| ContractError::Tendermint(e.to_string()))?; + let consensus_state = ctx + .consensus_state(&client_id, msg.height) + .map_err(|e| ContractError::Tendermint(e.to_string()))?; + + verify_non_membership::( + &client_state, + &msg.prefix, + &msg.proof, + &consensus_state.root, + msg.path, + ) + .map_err(|e| ContractError::Tendermint(e.to_string())) + .map(|_| to_binary(&QueryResponse::success())) + }, SudoMsg::VerifyUpgradeAndUpdateState(msg) => { let old_client_state = ctx .client_state(&client_id.clone()) @@ -342,49 +384,5 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { .map_err(|e| ContractError::Tendermint(format!("{e:?}"))) .map(|_| to_binary(&QueryResponse::success()))? }, - QueryMsg::VerifyMembership(msg) => { - let ctx = Context::::new_ro(deps, env); - let client_state = ctx - .client_state(&client_id) - .map_err(|e| ContractError::Tendermint(e.to_string()))?; - let msg = VerifyMembershipMsg::try_from(msg)?; - verify_delay_passed(&ctx, msg.height, msg.delay_time_period, msg.delay_block_period) - .map_err(|e| ContractError::Tendermint(e.to_string()))?; - let consensus_state = ctx - .consensus_state(&client_id, msg.height) - .map_err(|e| ContractError::Tendermint(e.to_string()))?; - verify_membership::( - &client_state, - &msg.prefix, - &msg.proof, - &consensus_state.root, - msg.path, - msg.value, - ) - .map_err(|e| ContractError::Tendermint(e.to_string()))?; - to_binary(&QueryResponse::success()) - }, - QueryMsg::VerifyNonMembership(msg) => { - let ctx = Context::::new_ro(deps, env); - let client_state = ctx - .client_state(&client_id) - .map_err(|e| ContractError::Tendermint(e.to_string()))?; - let msg = VerifyNonMembershipMsg::try_from(msg)?; - verify_delay_passed(&ctx, msg.height, msg.delay_time_period, msg.delay_block_period) - .map_err(|e| ContractError::Tendermint(e.to_string()))?; - let consensus_state = ctx - .consensus_state(&client_id, msg.height) - .map_err(|e| ContractError::Tendermint(e.to_string()))?; - - verify_non_membership::( - &client_state, - &msg.prefix, - &msg.proof, - &consensus_state.root, - msg.path, - ) - .map_err(|e| ContractError::Tendermint(e.to_string())) - .map(|_| to_binary(&QueryResponse::success()))? - }, } } diff --git a/light-clients/ics07-tendermint-cw/src/msg.rs b/light-clients/ics07-tendermint-cw/src/msg.rs index f5572a262..fd02a7fe5 100644 --- a/light-clients/ics07-tendermint-cw/src/msg.rs +++ b/light-clients/ics07-tendermint-cw/src/msg.rs @@ -129,6 +129,8 @@ pub enum SudoMsg { CheckSubstituteAndUpdateState(CheckSubstituteAndUpdateStateMsg), UpdateStateOnMisbehaviour(UpdateStateOnMisbehaviourMsgRaw), UpdateState(UpdateStateMsgRaw), + VerifyMembership(VerifyMembershipMsgRaw), + VerifyNonMembership(VerifyNonMembershipMsgRaw), VerifyUpgradeAndUpdateState(VerifyUpgradeAndUpdateStateMsgRaw), } @@ -140,8 +142,6 @@ pub enum QueryMsg { ExportMetadata(ExportMetadataMsg), Status(StatusMsg), TimestampAtHeight(TimestampAtHeightMsg), - VerifyMembership(VerifyMembershipMsgRaw), - VerifyNonMembership(VerifyNonMembershipMsgRaw), VerifyClientMessage(VerifyClientMessageRaw), } @@ -167,91 +167,6 @@ pub struct MerklePath { pub key_path: Vec, } -#[cw_serde] -pub struct VerifyMembershipMsgRaw { - #[schemars(with = "String")] - #[serde(with = "Base64", default)] - pub proof: Bytes, - pub path: MerklePath, - #[schemars(with = "String")] - #[serde(with = "Base64", default)] - pub value: Bytes, - pub height: HeightRaw, - pub delay_block_period: u64, - pub delay_time_period: u64, -} - -pub struct VerifyMembershipMsg { - pub prefix: CommitmentPrefix, - pub proof: CommitmentProofBytes, - pub path: Path, - pub value: Vec, - pub height: Height, - pub delay_block_period: u64, - pub delay_time_period: u64, -} - -impl TryFrom for VerifyMembershipMsg { - type Error = ContractError; - - fn try_from(mut raw: VerifyMembershipMsgRaw) -> Result { - let proof = CommitmentProofBytes::try_from(raw.proof)?; - let prefix = raw.path.key_path.remove(0).into_bytes(); - let path_str = raw.path.key_path.join(""); - let path = Path::from_str(&path_str)?; - let height = Height::from(raw.height); - Ok(Self { - proof, - path, - value: raw.value, - height, - prefix: CommitmentPrefix::try_from(prefix)?, - delay_block_period: raw.delay_block_period, - delay_time_period: raw.delay_time_period, - }) - } -} - -#[cw_serde] -pub struct VerifyNonMembershipMsgRaw { - #[schemars(with = "String")] - #[serde(with = "Base64", default)] - pub proof: Bytes, - pub path: MerklePath, - pub height: HeightRaw, - pub delay_block_period: u64, - pub delay_time_period: u64, -} - -pub struct VerifyNonMembershipMsg { - pub prefix: CommitmentPrefix, - pub proof: CommitmentProofBytes, - pub path: Path, - pub height: Height, - pub delay_block_period: u64, - pub delay_time_period: u64, -} - -impl TryFrom for VerifyNonMembershipMsg { - type Error = ContractError; - - fn try_from(mut raw: VerifyNonMembershipMsgRaw) -> Result { - let proof = CommitmentProofBytes::try_from(raw.proof)?; - let prefix = raw.path.key_path.remove(0).into_bytes(); - let path_str = raw.path.key_path.join(""); - let path = Path::from_str(&path_str)?; - let height = Height::from(raw.height); - Ok(Self { - proof, - path, - height, - prefix: CommitmentPrefix::try_from(prefix)?, - delay_block_period: raw.delay_block_period, - delay_time_period: raw.delay_time_period, - }) - } -} - #[cw_serde] pub struct ClientMessageRaw { #[schemars(with = "String")] @@ -346,6 +261,91 @@ impl TryFrom for UpdateStateMsg { #[cw_serde] pub struct CheckSubstituteAndUpdateStateMsg {} +#[cw_serde] +pub struct VerifyMembershipMsgRaw { + #[schemars(with = "String")] + #[serde(with = "Base64", default)] + pub proof: Bytes, + pub path: MerklePath, + #[schemars(with = "String")] + #[serde(with = "Base64", default)] + pub value: Bytes, + pub height: HeightRaw, + pub delay_block_period: u64, + pub delay_time_period: u64, +} + +pub struct VerifyMembershipMsg { + pub prefix: CommitmentPrefix, + pub proof: CommitmentProofBytes, + pub path: Path, + pub value: Vec, + pub height: Height, + pub delay_block_period: u64, + pub delay_time_period: u64, +} + +impl TryFrom for VerifyMembershipMsg { + type Error = ContractError; + + fn try_from(mut raw: VerifyMembershipMsgRaw) -> Result { + let proof = CommitmentProofBytes::try_from(raw.proof)?; + let prefix = raw.path.key_path.remove(0).into_bytes(); + let path_str = raw.path.key_path.join(""); + let path = Path::from_str(&path_str)?; + let height = Height::from(raw.height); + Ok(Self { + proof, + path, + value: raw.value, + height, + prefix: CommitmentPrefix::try_from(prefix)?, + delay_block_period: raw.delay_block_period, + delay_time_period: raw.delay_time_period, + }) + } +} + +#[cw_serde] +pub struct VerifyNonMembershipMsgRaw { + #[schemars(with = "String")] + #[serde(with = "Base64", default)] + pub proof: Bytes, + pub path: MerklePath, + pub height: HeightRaw, + pub delay_block_period: u64, + pub delay_time_period: u64, +} + +pub struct VerifyNonMembershipMsg { + pub prefix: CommitmentPrefix, + pub proof: CommitmentProofBytes, + pub path: Path, + pub height: Height, + pub delay_block_period: u64, + pub delay_time_period: u64, +} + +impl TryFrom for VerifyNonMembershipMsg { + type Error = ContractError; + + fn try_from(mut raw: VerifyNonMembershipMsgRaw) -> Result { + let proof = CommitmentProofBytes::try_from(raw.proof)?; + let prefix = raw.path.key_path.remove(0).into_bytes(); + let path_str = raw.path.key_path.join(""); + let path = Path::from_str(&path_str)?; + let height = Height::from(raw.height); + Ok(Self { + proof, + path, + height, + prefix: CommitmentPrefix::try_from(prefix)?, + delay_block_period: raw.delay_block_period, + delay_time_period: raw.delay_time_period, + }) + } +} + #[cw_serde] pub struct VerifyUpgradeAndUpdateStateMsgRaw { pub upgrade_client_state: WasmClientState, diff --git a/light-clients/ics10-grandpa-cw/src/contract.rs b/light-clients/ics10-grandpa-cw/src/contract.rs index e0730fe98..b6a3dae92 100644 --- a/light-clients/ics10-grandpa-cw/src/contract.rs +++ b/light-clients/ics10-grandpa-cw/src/contract.rs @@ -259,6 +259,36 @@ fn process_message( Ok(()).map(|_| to_binary(&ContractResult::success())) }, + SudoMsg::VerifyMembership(msg) => { + let msg = VerifyMembershipMsg::try_from(msg)?; + let consensus_state = ctx + .consensus_state(&client_id, msg.height) + .map_err(|e| ContractError::Grandpa(e.to_string()))?; + verify_membership::( + &msg.prefix, + &msg.proof, + &consensus_state.root, + msg.path, + msg.value, + ) + .map_err(|e| ContractError::Grandpa(e.to_string())) + .map(|_| to_binary(&ContractResult::success())) + }, + SudoMsg::VerifyNonMembership(msg) => { + let msg = VerifyNonMembershipMsg::try_from(msg)?; + let consensus_state = ctx + .consensus_state(&client_id, msg.height) + .map_err(|e| ContractError::Grandpa(e.to_string()))?; + + verify_non_membership::( + &msg.prefix, + &msg.proof, + &consensus_state.root, + msg.path, + ) + .map_err(|e| ContractError::Grandpa(e.to_string())) + .map(|_| to_binary(&ContractResult::success())) + }, SudoMsg::VerifyUpgradeAndUpdateState(msg) => { let old_client_state = ctx .client_state(&client_id) @@ -361,38 +391,6 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { .map(|_| to_binary(&QueryResponse::success()))?; f }, - QueryMsg::VerifyMembership(msg) => { - let ctx = Context::::new_ro(deps, env); - let msg = VerifyMembershipMsg::try_from(msg)?; - let consensus_state = ctx - .consensus_state(&client_id, msg.height) - .map_err(|e| ContractError::Grandpa(e.to_string()))?; - verify_membership::( - &msg.prefix, - &msg.proof, - &consensus_state.root, - msg.path, - msg.value, - ) - .map_err(|e| ContractError::Grandpa(e.to_string()))?; - to_binary(&QueryResponse::success()) - }, - QueryMsg::VerifyNonMembership(msg) => { - let ctx = Context::::new_ro(deps, env); - let msg = VerifyNonMembershipMsg::try_from(msg)?; - let consensus_state = ctx - .consensus_state(&client_id, msg.height) - .map_err(|e| ContractError::Grandpa(e.to_string()))?; - - verify_non_membership::( - &msg.prefix, - &msg.proof, - &consensus_state.root, - msg.path, - ) - .map_err(|e| ContractError::Grandpa(e.to_string())) - .map(|_| to_binary(&QueryResponse::success()))? - }, } } diff --git a/light-clients/ics10-grandpa-cw/src/msg.rs b/light-clients/ics10-grandpa-cw/src/msg.rs index db3ed6222..0cb651a16 100644 --- a/light-clients/ics10-grandpa-cw/src/msg.rs +++ b/light-clients/ics10-grandpa-cw/src/msg.rs @@ -148,6 +148,8 @@ pub enum SudoMsg { CheckSubstituteAndUpdateState(CheckSubstituteAndUpdateStateMsgRaw), UpdateStateOnMisbehaviour(UpdateStateOnMisbehaviourMsgRaw), UpdateState(UpdateStateMsgRaw), + VerifyMembership(VerifyMembershipMsgRaw), + VerifyNonMembership(VerifyNonMembershipMsgRaw), VerifyUpgradeAndUpdateState(VerifyUpgradeAndUpdateStateMsgRaw), } @@ -159,8 +161,6 @@ pub enum QueryMsg { ExportMetadata(ExportMetadataMsg), Status(StatusMsg), TimestampAtHeight(TimestampAtHeightMsg), - VerifyMembership(VerifyMembershipMsgRaw), - VerifyNonMembership(VerifyNonMembershipMsgRaw), VerifyClientMessage(VerifyClientMessageRaw), } @@ -186,78 +186,6 @@ pub struct MerklePath { pub key_path: Vec, } -#[cw_serde] -pub struct VerifyMembershipMsgRaw { - #[schemars(with = "String")] - #[serde(with = "Base64", default)] - pub proof: Bytes, - pub path: MerklePath, - #[schemars(with = "String")] - #[serde(with = "Base64", default)] - pub value: Bytes, - pub height: HeightRaw, - pub delay_block_period: u64, - pub delay_time_period: u64, -} - -pub struct VerifyMembershipMsg { - pub prefix: CommitmentPrefix, - pub proof: CommitmentProofBytes, - pub path: Path, - pub value: Vec, - pub height: Height, -} - -impl TryFrom for VerifyMembershipMsg { - type Error = ContractError; - - fn try_from(mut raw: VerifyMembershipMsgRaw) -> Result { - let proof = CommitmentProofBytes::try_from(raw.proof)?; - let prefix = raw.path.key_path.remove(0).into_bytes(); - let path_str = raw.path.key_path.join(""); - let path = Path::from_str(&path_str)?; - let height = Height::from(raw.height); - Ok(Self { - proof, - path, - value: raw.value, - height, - prefix: CommitmentPrefix::try_from(prefix)?, - }) - } -} - -#[cw_serde] -pub struct VerifyNonMembershipMsgRaw { - #[schemars(with = "String")] - #[serde(with = "Base64", default)] - pub proof: Bytes, - pub path: MerklePath, - pub height: HeightRaw, - pub delay_block_period: u64, - pub delay_time_period: u64, -} - -pub struct VerifyNonMembershipMsg { - pub prefix: CommitmentPrefix, - pub proof: CommitmentProofBytes, - pub path: Path, - pub height: Height, -} - -impl TryFrom for VerifyNonMembershipMsg { - type Error = ContractError; - - fn try_from(mut raw: VerifyNonMembershipMsgRaw) -> Result { - let proof = CommitmentProofBytes::try_from(raw.proof)?; - let prefix = raw.path.key_path.remove(0).into_bytes(); - let path_str = raw.path.key_path.join(""); - let path = Path::from_str(&path_str)?; - let height = Height::from(raw.height); - Ok(Self { proof, path, height, prefix: CommitmentPrefix::try_from(prefix)? }) - } -} - #[cw_serde] pub struct ClientMessageRaw { #[schemars(with = "String")] @@ -364,6 +292,77 @@ impl TryFrom for CheckSubstituteAndUpdateSt } } +#[cw_serde] +pub struct VerifyMembershipMsgRaw { + #[schemars(with = "String")] + #[serde(with = "Base64", default)] + pub proof: Bytes, + pub path: MerklePath, + #[schemars(with = "String")] + #[serde(with = "Base64", default)] + pub value: Bytes, + pub height: HeightRaw, + pub delay_block_period: u64, + pub delay_time_period: u64, +} + +pub struct VerifyMembershipMsg { + pub prefix: CommitmentPrefix, + pub proof: CommitmentProofBytes, + pub path: Path, + pub value: Vec, + pub height: Height, +} + +impl TryFrom for VerifyMembershipMsg { + type Error = ContractError; + + fn try_from(mut raw: VerifyMembershipMsgRaw) -> Result { + let proof = CommitmentProofBytes::try_from(raw.proof)?; + let prefix = raw.path.key_path.remove(0).into_bytes(); + let path_str = raw.path.key_path.join(""); + let path = Path::from_str(&path_str)?; + let height = Height::from(raw.height); + Ok(Self { + proof, + path, + value: raw.value, + height, + prefix: CommitmentPrefix::try_from(prefix)?, + }) + } +} + +#[cw_serde] +pub struct VerifyNonMembershipMsgRaw { + #[schemars(with = "String")] + #[serde(with = "Base64", default)] + pub proof: Bytes, + pub path: MerklePath, + pub height: HeightRaw, + pub delay_block_period: u64, + pub delay_time_period: u64, +} + +pub struct VerifyNonMembershipMsg { + pub prefix: CommitmentPrefix, + pub proof: CommitmentProofBytes, + pub path: Path, + pub height: Height, +} + +impl TryFrom for VerifyNonMembershipMsg { + type Error = ContractError; + + fn try_from(mut raw: VerifyNonMembershipMsgRaw) -> Result { + let proof = CommitmentProofBytes::try_from(raw.proof)?; + let prefix = raw.path.key_path.remove(0).into_bytes(); + let path_str = raw.path.key_path.join(""); + let path = Path::from_str(&path_str)?; + let height = Height::from(raw.height); + Ok(Self { proof, path, height, prefix: CommitmentPrefix::try_from(prefix)? }) + } +} #[cw_serde] pub struct VerifyUpgradeAndUpdateStateMsgRaw { pub upgrade_client_state: WasmClientState, From 4a8908085ab94bb3de6005a74f53c206cfcdb1b5 Mon Sep 17 00:00:00 2001 From: Steve Miskovetz Date: Thu, 5 Oct 2023 16:30:33 -0600 Subject: [PATCH 17/37] Change QueryResult to ContractResult for Verify(Non)Memberships --- light-clients/ics07-tendermint-cw/src/contract.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/light-clients/ics07-tendermint-cw/src/contract.rs b/light-clients/ics07-tendermint-cw/src/contract.rs index 61fd4217b..65cc3a7cc 100644 --- a/light-clients/ics07-tendermint-cw/src/contract.rs +++ b/light-clients/ics07-tendermint-cw/src/contract.rs @@ -267,7 +267,7 @@ fn process_message( msg.value, ) .map_err(|e| ContractError::Tendermint(e.to_string())) - .map(|_| to_binary(&QueryResponse::success())) + .map(|_| to_binary(&ContractResult::success())) }, SudoMsg::VerifyNonMembership(msg) => { let client_state = ctx @@ -288,7 +288,7 @@ fn process_message( msg.path, ) .map_err(|e| ContractError::Tendermint(e.to_string())) - .map(|_| to_binary(&QueryResponse::success())) + .map(|_| to_binary(&ContractResult::success())) }, SudoMsg::VerifyUpgradeAndUpdateState(msg) => { let old_client_state = ctx From 2b6fd6a71f19298ef48d07f4118ee0b3964d6323 Mon Sep 17 00:00:00 2001 From: Carlos Rodriguez Date: Fri, 27 Oct 2023 13:37:13 +0200 Subject: [PATCH 18/37] imp: rename checksubstituteandupdatestate to migrateclientstore --- light-clients/ics07-tendermint-cw/src/contract.rs | 2 +- light-clients/ics07-tendermint-cw/src/msg.rs | 4 ++-- light-clients/ics10-grandpa-cw/src/contract.rs | 6 +++--- light-clients/ics10-grandpa-cw/src/msg.rs | 10 +++++----- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/light-clients/ics07-tendermint-cw/src/contract.rs b/light-clients/ics07-tendermint-cw/src/contract.rs index 65cc3a7cc..48d49423b 100644 --- a/light-clients/ics07-tendermint-cw/src/contract.rs +++ b/light-clients/ics07-tendermint-cw/src/contract.rs @@ -238,7 +238,7 @@ fn process_message( Ok(to_binary(&ContractResult::success().heights(heights))) }) }, - SudoMsg::CheckSubstituteAndUpdateState(_msg) => + SudoMsg::MigrateClientStore(_msg) => check_substitute_and_update_state::(ctx) .map_err(|e| ContractError::Tendermint(e.to_string())) .and_then(|(cs, cu)| { diff --git a/light-clients/ics07-tendermint-cw/src/msg.rs b/light-clients/ics07-tendermint-cw/src/msg.rs index ffda696bc..5200cf1a6 100644 --- a/light-clients/ics07-tendermint-cw/src/msg.rs +++ b/light-clients/ics07-tendermint-cw/src/msg.rs @@ -117,7 +117,7 @@ impl ContractResult { #[cw_serde] pub enum SudoMsg { - CheckSubstituteAndUpdateState(CheckSubstituteAndUpdateStateMsg), + MigrateClientStore(MigrateClientStoreMsg), UpdateStateOnMisbehaviour(UpdateStateOnMisbehaviourMsgRaw), UpdateState(UpdateStateMsgRaw), VerifyMembership(VerifyMembershipMsgRaw), @@ -250,7 +250,7 @@ impl TryFrom for UpdateStateMsg { } #[cw_serde] -pub struct CheckSubstituteAndUpdateStateMsg {} +pub struct MigrateClientStoreMsg {} #[cw_serde] pub struct VerifyMembershipMsgRaw { diff --git a/light-clients/ics10-grandpa-cw/src/contract.rs b/light-clients/ics10-grandpa-cw/src/contract.rs index b6a3dae92..8fc86517b 100644 --- a/light-clients/ics10-grandpa-cw/src/contract.rs +++ b/light-clients/ics10-grandpa-cw/src/contract.rs @@ -19,7 +19,7 @@ use crate::{ ics23::FakeInner, log, msg::{ - CheckForMisbehaviourMsg, CheckSubstituteAndUpdateStateMsg, + CheckForMisbehaviourMsg, MigrateClientStoreMsg, ContractResult, SudoMsg, ExportMetadataMsg, QueryMsg, QueryResponse, StatusMsg, UpdateStateMsg, UpdateStateOnMisbehaviourMsg, VerifyClientMessage, VerifyMembershipMsg, VerifyNonMembershipMsg, VerifyUpgradeAndUpdateStateMsg, @@ -220,8 +220,8 @@ fn process_message( store_client_and_consensus_states(ctx, client_id.clone(), cs, cu) }) }, - SudoMsg::CheckSubstituteAndUpdateState(msg) => { - let _msg = CheckSubstituteAndUpdateStateMsg::try_from(msg)?; + SudoMsg::MigrateClientStore(msg) => { + let _msg = MigrateClientStoreMsg::try_from(msg)?; // manually load both states from the combined storage using the appropriate prefixes let mut old_client_state = ctx .client_state_prefixed(SUBJECT_PREFIX) diff --git a/light-clients/ics10-grandpa-cw/src/msg.rs b/light-clients/ics10-grandpa-cw/src/msg.rs index c2c1a3bd6..c038fab5a 100644 --- a/light-clients/ics10-grandpa-cw/src/msg.rs +++ b/light-clients/ics10-grandpa-cw/src/msg.rs @@ -136,7 +136,7 @@ pub struct ClientCreateRequest { #[cw_serde] pub enum SudoMsg { - CheckSubstituteAndUpdateState(CheckSubstituteAndUpdateStateMsgRaw), + MigrateClientStore(MigrateClientStoreMsgRaw), UpdateStateOnMisbehaviour(UpdateStateOnMisbehaviourMsgRaw), UpdateState(UpdateStateMsgRaw), VerifyMembership(VerifyMembershipMsgRaw), @@ -269,15 +269,15 @@ impl TryFrom for UpdateStateMsg { } #[cw_serde] -pub struct CheckSubstituteAndUpdateStateMsgRaw {} +pub struct MigrateClientStoreMsgRaw {} -pub struct CheckSubstituteAndUpdateStateMsg {} +pub struct MigrateClientStoreMsg {} -impl TryFrom for CheckSubstituteAndUpdateStateMsg { +impl TryFrom for MigrateClientStoreMsg { type Error = ContractError; fn try_from( - CheckSubstituteAndUpdateStateMsgRaw {}: CheckSubstituteAndUpdateStateMsgRaw, + MigrateClientStoreMsgRaw {}: MigrateClientStoreMsgRaw, ) -> Result { Ok(Self {}) } From 35607f59d61bad21bb00c63c90985a792a8436b8 Mon Sep 17 00:00:00 2001 From: Blas Rodriguez Irizar Date: Mon, 6 Nov 2023 18:18:37 +0100 Subject: [PATCH 19/37] ics10-grandpa-cw: decode consensus state to check for expiration --- light-clients/ics10-grandpa-cw/src/contract.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/light-clients/ics10-grandpa-cw/src/contract.rs b/light-clients/ics10-grandpa-cw/src/contract.rs index bb1c49cad..4bfd8786e 100644 --- a/light-clients/ics10-grandpa-cw/src/contract.rs +++ b/light-clients/ics10-grandpa-cw/src/contract.rs @@ -333,7 +333,7 @@ fn process_message( } #[cfg_attr(not(feature = "library"), entry_point)] -pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { +pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { let client_id = ClientId::from_str("08-wasm-0").expect("client id is valid"); match msg { QueryMsg::ClientTypeMsg(_) => unimplemented!("ClientTypeMsg"), @@ -351,7 +351,13 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { } else { let height = client_state.latest_height(); match get_consensus_state(deps, &client_id, height) { - Ok(_) => to_binary(&QueryResponse::status("Active".to_string())), + Ok(consensus_state_raw) => { + let consensus_state = Context::decode_consensus_state(&consensus_state_raw)?; + if client_state.expired(env.block.time - consensus_state.timestamp) { + return to_binary(&QueryResponse::status("Expired".to_string())); + } + to_binary(&QueryResponse::status("Active".to_string())) + }, Err(_) => to_binary(&QueryResponse::status("Expired".to_string())), } } From fe0470f59df20dc74b54cb73c2b2e26feaeb6753 Mon Sep 17 00:00:00 2001 From: Blas Rodriguez Irizar Date: Mon, 6 Nov 2023 21:00:50 +0100 Subject: [PATCH 20/37] compare in seconds --- light-clients/ics10-grandpa-cw/src/contract.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/light-clients/ics10-grandpa-cw/src/contract.rs b/light-clients/ics10-grandpa-cw/src/contract.rs index 4bfd8786e..a43c39206 100644 --- a/light-clients/ics10-grandpa-cw/src/contract.rs +++ b/light-clients/ics10-grandpa-cw/src/contract.rs @@ -353,7 +353,7 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { match get_consensus_state(deps, &client_id, height) { Ok(consensus_state_raw) => { let consensus_state = Context::decode_consensus_state(&consensus_state_raw)?; - if client_state.expired(env.block.time - consensus_state.timestamp) { + if client_state.expired(env.block.time.as_secs() - consensus_state.timestamp.as_seconds()) { return to_binary(&QueryResponse::status("Expired".to_string())); } to_binary(&QueryResponse::status("Active".to_string())) From 8b458d1f74fa2b07420b64880064f72c66f35baa Mon Sep 17 00:00:00 2001 From: Blas Rodriguez Irizar Date: Mon, 6 Nov 2023 23:06:36 +0100 Subject: [PATCH 21/37] add test --- Cargo.lock | 1 + light-clients/ics10-grandpa-cw/Cargo.toml | 2 + .../ics10-grandpa-cw/src/contract.rs | 69 ++++++++++++++++++- 3 files changed, 69 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b3209a3d0..000cfcce5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5139,6 +5139,7 @@ dependencies = [ "sp-runtime 7.0.0", "sp-runtime-interface 7.0.0", "sp-std 5.0.0", + "tendermint", "tendermint-proto", "thiserror", "twox-hash", diff --git a/light-clients/ics10-grandpa-cw/Cargo.toml b/light-clients/ics10-grandpa-cw/Cargo.toml index dd48aa8ff..43a87a451 100644 --- a/light-clients/ics10-grandpa-cw/Cargo.toml +++ b/light-clients/ics10-grandpa-cw/Cargo.toml @@ -61,6 +61,8 @@ hyperspace-primitives = { path = "../../hyperspace/primitives", features = ["tes pallet-ibc = { path = "../../contracts/pallet-ibc" } serde-json-wasm = { version = "0.5.0", default-features = false } serde_json = { version = "1.0.93", default-features = false } +tendermint = { git = "https://github.com/informalsystems/tendermint-rs", rev = "e81f7bf23d63ffbcd242381d1ce5e35da3515ff1", default-features = false } + [features] # for more explicit tests, cargo test --features=backtraces diff --git a/light-clients/ics10-grandpa-cw/src/contract.rs b/light-clients/ics10-grandpa-cw/src/contract.rs index a43c39206..dd31ca940 100644 --- a/light-clients/ics10-grandpa-cw/src/contract.rs +++ b/light-clients/ics10-grandpa-cw/src/contract.rs @@ -30,7 +30,7 @@ use byteorder::{ByteOrder, LittleEndian}; use core::hash::Hasher; #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; -use cosmwasm_std::{to_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult}; +use cosmwasm_std::{to_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult, StdError}; use cw_storage_plus::{Item, Map}; use digest::Digest; use grandpa_light_client_primitives::justification::AncestryChain; @@ -352,8 +352,8 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { let height = client_state.latest_height(); match get_consensus_state(deps, &client_id, height) { Ok(consensus_state_raw) => { - let consensus_state = Context::decode_consensus_state(&consensus_state_raw)?; - if client_state.expired(env.block.time.as_secs() - consensus_state.timestamp.as_seconds()) { + let consensus_state = Context::::decode_consensus_state(&consensus_state_raw).map_err(|e|StdError::serialize_err(e.to_string(), e.to_string()))?; + if client_state.expired(core::time::Duration::from_secs(env.block.time.seconds() - consensus_state.timestamp.unix_timestamp() as u64)) { return to_binary(&QueryResponse::status("Expired".to_string())); } to_binary(&QueryResponse::status("Active".to_string())) @@ -439,3 +439,66 @@ pub extern "C" fn ext_hashing_twox_64_version_1(data: i64) -> i32 { let out_ptr = Box::leak(hash).as_ptr(); out_ptr as i32 } + + +#[cfg(test)] +mod tests { + use cosmwasm_std::from_binary; + use cosmwasm_std::testing::{mock_dependencies, mock_env, mock_info}; + use tendermint::Time; + use ibc::core::ics02_client::client_state::ClientState as _; + + use crate::ics23::ClientStates; + + use super::*; + #[test] + fn test_query() { + + let mut deps = mock_dependencies(); + let env = mock_env(); + + + for (expected, offset) in [("Active", 0i64), ("Expired", env.block.time.seconds() as i64 - 10), ("Frozen", 0i64)] { + let mut client_state = ics10_grandpa::client_state::ClientState::::default(); + let mut consensus_state = ics10_grandpa::consensus_state::ConsensusState::new(vec![], Time::from_unix_timestamp(0, 0).unwrap()); + let height = Height { revision_number: 0, revision_height: 1000}; + client_state.latest_para_height = height.revision_height as _; + + + consensus_state.timestamp = Time::from_unix_timestamp(env.block.time.seconds() as i64 - offset, 0).unwrap(); + let deps_mut = deps.as_mut(); + let mut client_states = ClientStates::new(deps_mut.storage); + if expected == "Frozen" { + let height = Height { revision_number: 0, revision_height: height.revision_height - 100}; + client_state = client_state.with_frozen_height(height.clone()).unwrap(); + } + + client_states.insert(client_state.encode_to_vec().unwrap()); + + let mut context = Context::new(deps_mut, env.clone()); + context.store_client_state(ClientId::default(), client_state).unwrap(); + context.store_consensus_state(ClientId::default(), height , consensus_state).unwrap(); + + let resp = query( + deps.as_ref(), + mock_env(), + QueryMsg::Status(StatusMsg{}) + ).unwrap(); + + instantiate( + deps.as_mut(), + env.clone(), + mock_info("sender", &[]), + InstantiateMsg { } , + ) + .unwrap(); + + let resp: QueryResponse = from_binary(&resp).unwrap(); + + assert_eq!( + resp, + QueryResponse::status(expected.to_string()) + ); + } + } +} \ No newline at end of file From c3964e2d53a504b8ac831efff82dc11117585b2c Mon Sep 17 00:00:00 2001 From: Steve Miskovetz Date: Fri, 10 Nov 2023 16:46:03 -0700 Subject: [PATCH 22/37] Fix MigrateClientStore --- .../ics07-tendermint-cw/src/context.rs | 2 +- light-clients/ics10-grandpa-cw/src/context.rs | 2 +- .../ics10-grandpa-cw/src/contract.rs | 42 +++---------------- 3 files changed, 7 insertions(+), 39 deletions(-) diff --git a/light-clients/ics07-tendermint-cw/src/context.rs b/light-clients/ics07-tendermint-cw/src/context.rs index 8ddf90ace..ef723691a 100644 --- a/light-clients/ics07-tendermint-cw/src/context.rs +++ b/light-clients/ics07-tendermint-cw/src/context.rs @@ -167,7 +167,7 @@ where let client_states = ReadonlyClientStates::new(self.storage()); let code_hash = match self.code_hash.clone() { None => { - let encoded_wasm_client_state = client_states.get().ok_or_else(|| { + let encoded_wasm_client_state = client_states.get_prefixed(prefix).ok_or_else(|| { ContractError::Tendermint( Error::client_not_found(ClientId::new("x", 1).unwrap()).to_string(), ) diff --git a/light-clients/ics10-grandpa-cw/src/context.rs b/light-clients/ics10-grandpa-cw/src/context.rs index f3f74a8f2..0c859f74d 100644 --- a/light-clients/ics10-grandpa-cw/src/context.rs +++ b/light-clients/ics10-grandpa-cw/src/context.rs @@ -185,7 +185,7 @@ where let client_states = ReadonlyClientStates::new(self.storage()); let code_hash = match self.code_hash.clone() { None => { - let encoded_wasm_client_state = client_states.get().ok_or_else(|| { + let encoded_wasm_client_state = client_states.get_prefixed(prefix).ok_or_else(|| { ContractError::Grandpa( Error::client_not_found(ClientId::new("x", 1).unwrap()).to_string(), ) diff --git a/light-clients/ics10-grandpa-cw/src/contract.rs b/light-clients/ics10-grandpa-cw/src/contract.rs index ce0cb7793..61367b8e5 100644 --- a/light-clients/ics10-grandpa-cw/src/contract.rs +++ b/light-clients/ics10-grandpa-cw/src/contract.rs @@ -19,7 +19,7 @@ use crate::{ ics23::FakeInner, log, msg::{ - CheckForMisbehaviourMsg, MigrateClientStoreMsg, + CheckForMisbehaviourMsg, ContractResult, SudoMsg, ExportMetadataMsg, QueryMsg, QueryResponse, StatusMsg, UpdateStateMsg, UpdateStateOnMisbehaviourMsg, VerifyClientMessage, VerifyMembershipMsg, VerifyNonMembershipMsg, VerifyUpgradeAndUpdateStateMsg, @@ -220,46 +220,14 @@ fn process_message( store_client_and_consensus_states(ctx, client_id.clone(), cs, cu) }) }, - SudoMsg::MigrateClientStore(msg) => { - let _msg = MigrateClientStoreMsg::try_from(msg)?; - // manually load both states from the combined storage using the appropriate prefixes - let mut old_client_state = ctx - .client_state_prefixed(SUBJECT_PREFIX) - .map_err(|e| ContractError::Grandpa(e.to_string()))?; + SudoMsg::MigrateClientStore(_msg) => { + // load the substitute client state from the combined storage using the appropriate prefix let substitute_client_state = ctx .client_state_prefixed(SUBSTITUTE_PREFIX) .map_err(|e| ContractError::Grandpa(e.to_string()))?; - // Check that the substitute client state is valid: - // all fields should be the same as in the old state, except for the `relay_chain`, - // `para_id`, `latest_para_height`, `latest_relay_height`, `latest_relay_hash`, - // `frozen_height`, `current_authorities`, `current_set_id` - let ClientState { - relay_chain, - latest_relay_height, - latest_relay_hash, - frozen_height, - latest_para_height, - para_id, - current_set_id, - current_authorities, - _phantom, - } = substitute_client_state.clone(); - old_client_state.relay_chain = relay_chain; - old_client_state.para_id = para_id; - old_client_state.latest_para_height = latest_para_height; - old_client_state.latest_relay_height = latest_relay_height; - old_client_state.latest_relay_hash = latest_relay_hash; - old_client_state.frozen_height = frozen_height; - old_client_state.current_authorities = current_authorities.clone(); - old_client_state.current_set_id = current_set_id; - - if old_client_state != substitute_client_state { - return Err(ContractError::Grandpa( - "subject client state does not match substitute client state".to_string(), - )) - } - let substitute_client_state = old_client_state; + // No items for the grandpa client state are required to be the same + let height = substitute_client_state.latest_height(); // consensus state should be replaced as well let substitute_consensus_state = From 44ef432fdb228118efc525d480b0cc1f73cfda9a Mon Sep 17 00:00:00 2001 From: Steve Miskovetz Date: Sun, 12 Nov 2023 16:38:45 -0700 Subject: [PATCH 23/37] Re-add timestamp functionality --- light-clients/ics08-wasm/src/consensus_state.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/light-clients/ics08-wasm/src/consensus_state.rs b/light-clients/ics08-wasm/src/consensus_state.rs index 3b4b829ac..9921ae23d 100644 --- a/light-clients/ics08-wasm/src/consensus_state.rs +++ b/light-clients/ics08-wasm/src/consensus_state.rs @@ -70,7 +70,7 @@ where } fn timestamp(&self) -> Timestamp { - unimplemented!() + self.inner.timestamp() } fn encode_to_vec(&self) -> Result, tendermint_proto::Error> { From f12c44a589d540ee3f378f20744695d33c69968e Mon Sep 17 00:00:00 2001 From: Steve Miskovetz Date: Mon, 13 Nov 2023 14:34:43 -0700 Subject: [PATCH 24/37] TimestampAtHeight should return timestamp in nanos instead of seconds --- light-clients/ics07-tendermint-cw/src/contract.rs | 2 +- light-clients/ics10-grandpa-cw/src/contract.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/light-clients/ics07-tendermint-cw/src/contract.rs b/light-clients/ics07-tendermint-cw/src/contract.rs index 70083e455..204eac0c1 100644 --- a/light-clients/ics07-tendermint-cw/src/contract.rs +++ b/light-clients/ics07-tendermint-cw/src/contract.rs @@ -370,7 +370,7 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { let consensus_state = ctx .consensus_state(&client_id, msg.height) .map_err(|e| ContractError::Tendermint(e.to_string()))?; - to_binary(&QueryResponse::success().timestamp(consensus_state.timestamp.unix_timestamp().unsigned_abs())) + to_binary(&QueryResponse::success().timestamp(consensus_state.timestamp.unix_timestamp_nanos().unsigned_abs() as u64)) }, QueryMsg::VerifyClientMessage(msg) => { let ctx = Context::::new_ro(deps, env); diff --git a/light-clients/ics10-grandpa-cw/src/contract.rs b/light-clients/ics10-grandpa-cw/src/contract.rs index 61367b8e5..3425f2d2b 100644 --- a/light-clients/ics10-grandpa-cw/src/contract.rs +++ b/light-clients/ics10-grandpa-cw/src/contract.rs @@ -340,7 +340,7 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { let consensus_state = ctx .consensus_state(&client_id, msg.height) .map_err(|e| ContractError::Grandpa(e.to_string()))?; - to_binary(&QueryResponse::success().timestamp(consensus_state.timestamp.unix_timestamp().unsigned_abs())) + to_binary(&QueryResponse::success().timestamp(consensus_state.timestamp.unix_timestamp_nanos().unsigned_abs() as u64)) }, QueryMsg::VerifyClientMessage(msg) => { let ctx = Context::::new_ro(deps, env); From 3a839080b19739ee1a85a3eec33eb39cf606feb1 Mon Sep 17 00:00:00 2001 From: Carlos Rodriguez Date: Wed, 15 Nov 2023 11:40:42 +0100 Subject: [PATCH 25/37] rename code_hash to checksum --- contracts/pallet-ibc/src/client.rs | 4 ++-- contracts/pallet-ibc/src/events.rs | 12 +++++----- contracts/pallet-ibc/src/light_clients.rs | 4 ++-- hyperspace/core/src/chain.rs | 8 +++---- hyperspace/core/src/command.rs | 8 +++---- hyperspace/core/src/macros.rs | 24 +++++++++---------- hyperspace/core/src/substrate/macros.rs | 4 ++-- hyperspace/cosmos/src/client.rs | 2 +- hyperspace/cosmos/src/events.rs | 10 ++++---- hyperspace/cosmos/src/provider.rs | 4 ++-- hyperspace/parachain/src/lib.rs | 2 +- hyperspace/parachain/src/provider.rs | 6 ++--- .../testsuite/tests/parachain_cosmos.rs | 12 +++++----- .../testsuite/tests/parachain_parachain.rs | 4 ++-- ibc/modules/src/core/ics02_client/events.rs | 8 +++---- .../src/prost/ibc.lightclients.wasm.v1.rs | 6 ++--- .../ics07-tendermint-cw/src/client.rs | 12 +++++----- .../ics07-tendermint-cw/src/context.rs | 14 +++++------ .../ics07-tendermint-cw/src/contract.rs | 2 +- light-clients/ics08-wasm/src/client_def.rs | 8 +++---- light-clients/ics08-wasm/src/client_state.rs | 8 +++---- light-clients/ics10-grandpa-cw/src/client.rs | 12 +++++----- light-clients/ics10-grandpa-cw/src/context.rs | 14 +++++------ .../ics10-grandpa-cw/src/contract.rs | 2 +- 24 files changed, 95 insertions(+), 95 deletions(-) diff --git a/contracts/pallet-ibc/src/client.rs b/contracts/pallet-ibc/src/client.rs index b546bfc43..a4bc2e61d 100644 --- a/contracts/pallet-ibc/src/client.rs +++ b/contracts/pallet-ibc/src/client.rs @@ -30,7 +30,7 @@ pub struct HostConsensusProof { pub header: Vec, pub extrinsic: Vec, pub extrinsic_proof: Vec>, - pub code_hash: Option>, + pub checksum: Option>, } impl ClientReader for Context @@ -285,7 +285,7 @@ where AnyConsensusState::wasm(cs).map_err(ICS02Error::encode)? }, _ => - if connection_proof.code_hash.is_some() { + if connection_proof.checksum.is_some() { log::trace!(target: "pallet_ibc", "in client : [host_consensus_state] >> using wasm code id"); AnyConsensusState::wasm(cs).map_err(ICS02Error::encode)? } else { diff --git a/contracts/pallet-ibc/src/events.rs b/contracts/pallet-ibc/src/events.rs index 97c5ddbc5..8071b78dd 100644 --- a/contracts/pallet-ibc/src/events.rs +++ b/contracts/pallet-ibc/src/events.rs @@ -4,7 +4,7 @@ use ibc::{ core::{ ics02_client::{ events as ClientEvents, - events::{CodeHash, NewBlock}, + events::{Checksum, NewBlock}, }, ics03_connection::events as ConnectionEvents, ics04_channel::{events as ChannelEvents, packet::Packet}, @@ -218,7 +218,7 @@ pub enum IbcEvent { /// App module AppModule { kind: Vec, module_id: Vec }, /// Push WASM Code - PushWasmCode { wasm_code_hash: CodeHash }, + PushWasmCode { wasm_checksum: Checksum }, } impl From for IbcEvent { @@ -439,8 +439,8 @@ impl From for IbcEvent { module_id: ev.module_name.to_string().as_bytes().to_vec(), }, RawIbcEvent::PushWasmCode(ev) => { - let wasm_code_hash = ev.0; - IbcEvent::PushWasmCode { wasm_code_hash } + let wasm_checksum = ev.0; + IbcEvent::PushWasmCode { wasm_checksum } }, } } @@ -545,8 +545,8 @@ impl TryFrom for RawIbcEvent { consensus_height: Height::new(consensus_revision_number, consensus_height), }, ))), - IbcEvent::PushWasmCode { wasm_code_hash } => - Ok(RawIbcEvent::PushWasmCode(ClientEvents::PushWasmCode(wasm_code_hash))), + IbcEvent::PushWasmCode { wasm_checksum } => + Ok(RawIbcEvent::PushWasmCode(ClientEvents::PushWasmCode(wasm_checksum))), IbcEvent::OpenInitConnection { revision_height, revision_number, diff --git a/contracts/pallet-ibc/src/light_clients.rs b/contracts/pallet-ibc/src/light_clients.rs index 14428a4e6..6bbe179c3 100644 --- a/contracts/pallet-ibc/src/light_clients.rs +++ b/contracts/pallet-ibc/src/light_clients.rs @@ -274,13 +274,13 @@ impl AnyClientState { } impl AnyClientState { - pub fn wasm(inner: Self, code_hash: Bytes) -> Result { + pub fn wasm(inner: Self, checksum: Bytes) -> Result { Ok(Self::Wasm( ics08_wasm::client_state::ClientState:: { data: inner.encode_to_vec()?, latest_height: inner.latest_height(), inner: Box::new(inner), - code_hash, + checksum, _phantom: Default::default(), }, )) diff --git a/hyperspace/core/src/chain.rs b/hyperspace/core/src/chain.rs index 647aafad7..2517d8892 100644 --- a/hyperspace/core/src/chain.rs +++ b/hyperspace/core/src/chain.rs @@ -31,7 +31,7 @@ use ibc::{ core::{ ics02_client::{ client_state::ClientType, - events::{CodeHash, UpdateClient}, + events::{Checksum, UpdateClient}, msgs::{create_client::MsgCreateAnyClient, update_client::MsgUpdateAnyClient}, }, ics03_connection::msgs::{ @@ -101,7 +101,7 @@ chains! { Cosmos(CosmosClientConfig, CosmosClient), } -fn wrap_any_msg_into_wasm(msg: Any, code_hash: Bytes) -> Result { +fn wrap_any_msg_into_wasm(msg: Any, checksum: Bytes) -> Result { // TODO: consider rewriting with Ics26Envelope use ibc::core::{ ics02_client::msgs::{ @@ -119,7 +119,7 @@ fn wrap_any_msg_into_wasm(msg: Any, code_hash: Bytes) -> Result::decode_vec(&msg.value).unwrap(); msg_decoded.consensus_state = AnyConsensusState::wasm(msg_decoded.consensus_state)?; - msg_decoded.client_state = AnyClientState::wasm(msg_decoded.client_state, code_hash)?; + msg_decoded.client_state = AnyClientState::wasm(msg_decoded.client_state, checksum)?; msg_decoded.to_any() }, CONN_OPEN_TRY_TYPE_URL => { @@ -147,5 +147,5 @@ fn wrap_any_msg_into_wasm(msg: Any, code_hash: Bytes) -> Result, - pub code_hash: Bytes, + pub checksum: Bytes, } diff --git a/hyperspace/core/src/command.rs b/hyperspace/core/src/command.rs index 1b2cb8385..eb4e4e4bb 100644 --- a/hyperspace/core/src/command.rs +++ b/hyperspace/core/src/command.rs @@ -105,10 +105,10 @@ impl UploadWasmCmd { let mut config: AnyConfig = toml::from_str(&file_content)?; let client = config.clone().into_client().await?; let wasm = tokio::fs::read(&self.wasm_path).await?; - let code_hash = client.upload_wasm(wasm).await?; - let code_hash_str = hex::encode(code_hash); - println!("{code_hash_str}"); - config.set_wasm_code_hash(code_hash_str); + let checksum = client.upload_wasm(wasm).await?; + let checksum_str = hex::encode(checksum); + println!("{checksum_str}"); + config.set_wasm_checksum(checksum_str); Ok(config) } diff --git a/hyperspace/core/src/macros.rs b/hyperspace/core/src/macros.rs index 90df509ac..da02474ac 100644 --- a/hyperspace/core/src/macros.rs +++ b/hyperspace/core/src/macros.rs @@ -808,7 +808,7 @@ macro_rules! chains { Self::Wasm(chain) => { let messages = messages .into_iter() - .map(|msg| wrap_any_msg_into_wasm(msg, chain.code_hash.clone())) + .map(|msg| wrap_any_msg_into_wasm(msg, chain.checksum.clone())) .collect::, _>>()?; chain.inner.submit(messages).await.map_err(AnyError::into) }, @@ -989,15 +989,15 @@ macro_rules! chains { impl AnyConfig { pub async fn into_client(self) -> anyhow::Result { - let maybe_wasm_code_hash = self.wasm_code_hash(); + let maybe_wasm_checksum = self.wasm_checksum(); let chain = match self { $( $(#[$($meta)*])* AnyConfig::$name(config) => AnyChain::$name(<$client>::new(config).await?), )* }; - if let Some(code_hash) = maybe_wasm_code_hash { - Ok(AnyChain::Wasm(WasmChain { inner: Box::new(chain), code_hash })) + if let Some(checksum) = maybe_wasm_checksum { + Ok(AnyChain::Wasm(WasmChain { inner: Box::new(chain), checksum })) } else { Ok(chain) } @@ -1036,25 +1036,25 @@ macro_rules! chains { } } - pub fn wasm_code_hash(&self) -> Option { - let maybe_code_hash = match self { + pub fn wasm_checksum(&self) -> Option { + let maybe_checksum = match self { $( $(#[$($meta)*])* - Self::$name(chain) => chain.wasm_code_hash.as_ref(), + Self::$name(chain) => chain.wasm_checksum.as_ref(), )* }; - let maybe_code_hash = - maybe_code_hash.map(|s| hex::decode(s).expect("Wasm code id is hex-encoded")); + let maybe_checksum = + maybe_checksum.map(|s| hex::decode(s).expect("Wasm checksum is hex-encoded")); - maybe_code_hash + maybe_checksum } - pub fn set_wasm_code_hash(&mut self, code_hash: String) { + pub fn set_wasm_checksum(&mut self, checksum: String) { match self { $( $(#[$($meta)*])* Self::$name(chain) => { - chain.wasm_code_hash = Some(code_hash); + chain.wasm_checksum = Some(checksum); }, )* } diff --git a/hyperspace/core/src/substrate/macros.rs b/hyperspace/core/src/substrate/macros.rs index c1c792e1c..6265f5594 100644 --- a/hyperspace/core/src/substrate/macros.rs +++ b/hyperspace/core/src/substrate/macros.rs @@ -487,8 +487,8 @@ macro_rules! define_ibc_event_wrapper { RawIbcEvent::AppModule { kind, module_id }, MetadataIbcEvent::Empty => RawIbcEvent::Empty, MetadataIbcEvent::ChainError => RawIbcEvent::ChainError, - MetadataIbcEvent::PushWasmCode{ wasm_code_id: wasm_code_hash } => RawIbcEvent::PushWasmCode { - wasm_code_hash + MetadataIbcEvent::PushWasmCode{ wasm_checksum } => RawIbcEvent::PushWasmCode { + wasm_checksum }, $($additional)* } diff --git a/hyperspace/cosmos/src/client.rs b/hyperspace/cosmos/src/client.rs index 61ee66c97..d01241722 100644 --- a/hyperspace/cosmos/src/client.rs +++ b/hyperspace/cosmos/src/client.rs @@ -212,7 +212,7 @@ pub struct CosmosClientConfig { pub max_tx_size: usize, /// All the client states and headers will be wrapped in WASM ones using the WASM code ID. #[serde(default)] - pub wasm_code_hash: Option, + pub wasm_checksum: Option, /* Here is a list of dropped configuration parameters from Hermes Config.toml that could be set to default values or removed for the MVP phase: diff --git a/hyperspace/cosmos/src/events.rs b/hyperspace/cosmos/src/events.rs index df014df28..b4e71ef8a 100644 --- a/hyperspace/cosmos/src/events.rs +++ b/hyperspace/cosmos/src/events.rs @@ -211,17 +211,17 @@ pub fn client_misbehaviour_try_from_abci_event( pub fn push_wasm_code_try_from_abci_event( abci_event: &AbciEvent, ) -> Result { - let mut code_hash = None; + let mut checksum = None; for tag in &abci_event.attributes { let key = tag.key.as_str(); let value = tag.value.as_str(); - if let client_events::WASM_CODE_HASH_ATTRIBUTE_KEY = key { - code_hash = Some(hex::decode(value).map_err(IbcEventError::from_hex_error)?) + if let client_events::WASM_CHECKSUM_ATTRIBUTE_KEY = key { + checksum = Some(hex::decode(value).map_err(IbcEventError::from_hex_error)?) } } - Ok(client_events::PushWasmCode(code_hash.ok_or_else(|| { - IbcEventError::missing_key(client_events::WASM_CODE_HASH_ATTRIBUTE_KEY.to_owned()) + Ok(client_events::PushWasmCode(checksum.ok_or_else(|| { + IbcEventError::missing_key(client_events::WASM_CHECKSUM_ATTRIBUTE_KEY.to_owned()) })?)) } diff --git a/hyperspace/cosmos/src/provider.rs b/hyperspace/cosmos/src/provider.rs index b59b56723..caea268ba 100644 --- a/hyperspace/cosmos/src/provider.rs +++ b/hyperspace/cosmos/src/provider.rs @@ -1286,7 +1286,7 @@ where .flat_map(|e| ibc_event_try_from_abci_event(e, height).ok().into_iter()) .filter(|e| matches!(e, IbcEvent::PushWasmCode(_))) .collect::>(); - let code_hash = if result.len() != 1 { + let checksum = if result.len() != 1 { return Err(Error::from(format!( "Expected exactly one PushWasmCode event, found {}", result.len() @@ -1309,7 +1309,7 @@ where // Error::from(format!("Failed to upload wasm code to grpc endpoint: {:?}", e)) // })?; - Ok(code_hash) + Ok(checksum) } } diff --git a/hyperspace/parachain/src/lib.rs b/hyperspace/parachain/src/lib.rs index fd64e857e..525ce7676 100644 --- a/hyperspace/parachain/src/lib.rs +++ b/hyperspace/parachain/src/lib.rs @@ -187,7 +187,7 @@ pub struct ParachainClientConfig { pub key_type: String, /// All the client states and headers will be wrapped in WASM ones using the WASM code ID. #[serde(default)] - pub wasm_code_hash: Option, + pub wasm_checksum: Option, } impl ParachainClient diff --git a/hyperspace/parachain/src/provider.rs b/hyperspace/parachain/src/provider.rs index 4866800a9..4beba8b72 100644 --- a/hyperspace/parachain/src/provider.rs +++ b/hyperspace/parachain/src/provider.rs @@ -561,8 +561,8 @@ where fetch_timestamp_extrinsic_with_proof(&self.para_client, Some(header.hash())) .await .map_err(Error::BeefyProver)?; - let code_hash = if let AnyClientState::Wasm(client_state) = &client_state { - Some(client_state.code_hash.clone()) + let checksum = if let AnyClientState::Wasm(client_state) = &client_state { + Some(client_state.checksum.clone()) } else { None }; @@ -570,7 +570,7 @@ where header: header.encode(), extrinsic: extrinsic_with_proof.ext, extrinsic_proof: extrinsic_with_proof.proof, - code_hash, + checksum, }; Ok(Some(host_consensus_proof.encode())) } diff --git a/hyperspace/testsuite/tests/parachain_cosmos.rs b/hyperspace/testsuite/tests/parachain_cosmos.rs index b948f91c3..945464ebd 100644 --- a/hyperspace/testsuite/tests/parachain_cosmos.rs +++ b/hyperspace/testsuite/tests/parachain_cosmos.rs @@ -86,7 +86,7 @@ async fn setup_clients() -> (AnyChain, AnyChain) { finality_protocol: FinalityProtocol::Grandpa, private_key: "//Alice".to_string(), key_type: "sr25519".to_string(), - wasm_code_hash: None, + wasm_checksum: None, }; let mut config_b = CosmosClientConfig { @@ -106,7 +106,7 @@ async fn setup_clients() -> (AnyChain, AnyChain) { mnemonic: "oxygen fall sure lava energy veteran enroll frown question detail include maximum" .to_string(), - wasm_code_hash: None, + wasm_checksum: None, channel_whitelist: vec![], common: CommonClientConfig { skip_optional_client_updates: true, @@ -118,8 +118,8 @@ async fn setup_clients() -> (AnyChain, AnyChain) { let chain_b = CosmosClient::::new(config_b.clone()).await.unwrap(); let wasm_data = tokio::fs::read(&args.wasm_path).await.expect("Failed to read wasm file"); - let code_hash = match chain_b.upload_wasm(wasm_data.clone()).await { - Ok(code_hash) => code_hash, + let checksum = match chain_b.upload_wasm(wasm_data.clone()).await { + Ok(checksum) => checksum, Err(e) => { let e_str = format!("{e:?}"); if !e_str.contains("wasm code already exists") { @@ -128,8 +128,8 @@ async fn setup_clients() -> (AnyChain, AnyChain) { sha2_256(&wasm_data).to_vec() }, }; - let code_hash_str = hex::encode(code_hash); - config_b.wasm_code_hash = Some(code_hash_str); + let checksum_str = hex::encode(checksum); + config_b.wasm_checksum = Some(checksum_str); let mut chain_a_wrapped = AnyConfig::Parachain(config_a).into_client().await.unwrap(); let mut chain_b_wrapped = AnyConfig::Cosmos(config_b).into_client().await.unwrap(); diff --git a/hyperspace/testsuite/tests/parachain_parachain.rs b/hyperspace/testsuite/tests/parachain_parachain.rs index 3b02bed88..80a8f7995 100644 --- a/hyperspace/testsuite/tests/parachain_parachain.rs +++ b/hyperspace/testsuite/tests/parachain_parachain.rs @@ -73,7 +73,7 @@ async fn setup_clients() -> (ParachainClient, ParachainClient (ParachainClient, ParachainClient::new(config_a).await.unwrap(); diff --git a/ibc/modules/src/core/ics02_client/events.rs b/ibc/modules/src/core/ics02_client/events.rs index 3eed21021..74a43193c 100644 --- a/ibc/modules/src/core/ics02_client/events.rs +++ b/ibc/modules/src/core/ics02_client/events.rs @@ -34,8 +34,8 @@ pub const CLIENT_TYPE_ATTRIBUTE_KEY: &str = "client_type"; /// The content of the `key` field for the attribute containing the height. pub const CONSENSUS_HEIGHT_ATTRIBUTE_KEY: &str = "consensus_height"; -/// The content of the `key` field for the attribute containing WASM code ID. -pub const WASM_CODE_HASH_ATTRIBUTE_KEY: &str = "wasm_code_hash"; +/// The content of the `key` field for the attribute containing WASM checksum. +pub const WASM_CHECKSUM_ATTRIBUTE_KEY: &str = "wasm_checksum"; /// NewBlock event signals the committing & execution of a new block. // TODO - find a better place for NewBlock @@ -264,11 +264,11 @@ impl From for IbcEvent { } } -pub type CodeHash = Vec; +pub type Checksum = Vec; /// Signals a recent pushed WASM code to the chain. #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize)] -pub struct PushWasmCode(pub CodeHash); +pub struct PushWasmCode(pub Checksum); impl From for IbcEvent { fn from(v: PushWasmCode) -> Self { diff --git a/ibc/proto/src/prost/ibc.lightclients.wasm.v1.rs b/ibc/proto/src/prost/ibc.lightclients.wasm.v1.rs index 2713ed1ab..0e9d9c5ce 100644 --- a/ibc/proto/src/prost/ibc.lightclients.wasm.v1.rs +++ b/ibc/proto/src/prost/ibc.lightclients.wasm.v1.rs @@ -12,7 +12,7 @@ pub struct MsgPushNewWasmCode { #[derive(Clone, PartialEq, ::prost::Message)] pub struct MsgPushNewWasmCodeResponse { #[prost(bytes = "vec", tag = "1")] - pub code_hash: ::prost::alloc::vec::Vec, + pub checksum: ::prost::alloc::vec::Vec, } /// Generated client implementations. #[cfg(feature = "client")] @@ -238,7 +238,7 @@ pub mod msg_server { #[derive(Clone, PartialEq, ::prost::Message)] pub struct WasmCodeQuery { #[prost(string, tag = "1")] - pub code_hash: ::prost::alloc::string::String, + pub checksum: ::prost::alloc::string::String, } /// WasmCode response #[allow(clippy::derive_partial_eq_without_eq)] @@ -475,7 +475,7 @@ pub struct ClientState { #[prost(bytes = "vec", tag = "1")] pub data: ::prost::alloc::vec::Vec, #[prost(bytes = "vec", tag = "2")] - pub code_hash: ::prost::alloc::vec::Vec, + pub checksum: ::prost::alloc::vec::Vec, #[prost(message, optional, tag = "3")] pub latest_height: ::core::option::Option, } diff --git a/light-clients/ics07-tendermint-cw/src/client.rs b/light-clients/ics07-tendermint-cw/src/client.rs index 87de17eac..c5d192107 100644 --- a/light-clients/ics07-tendermint-cw/src/client.rs +++ b/light-clients/ics07-tendermint-cw/src/client.rs @@ -26,7 +26,7 @@ use ibc::{ client_state::ClientType, context::{ClientKeeper, ClientReader, ClientTypes}, error::Error, - events::CodeHash, + events::Checksum, }, ics24_host::identifier::ClientId, }, @@ -184,7 +184,7 @@ impl<'a, H: HostFunctionsProvider + 'static> ClientKeeper for Context<'a, H> { client_state: Self::AnyClientState, ) -> Result<(), Error> { let client_states = ReadonlyClientStates::new(self.storage()); - let code_hash = match self.code_hash.clone() { + let checksum = match self.checksum.clone() { None => { let encoded_wasm_client_state = client_states .get() @@ -201,12 +201,12 @@ impl<'a, H: HostFunctionsProvider + 'static> ClientKeeper for Context<'a, H> { e )) })?; - wasm_client_state.code_hash + wasm_client_state.checksum }, Some(x) => x, }; - let encoded = Self::encode_client_state(client_state, code_hash)?; + let encoded = Self::encode_client_state(client_state, checksum)?; let mut client_state_storage = ClientStates::new(self.storage_mut()); client_state_storage.insert(encoded); Ok(()) @@ -292,11 +292,11 @@ impl<'a, H: Clone> Context<'a, H> { pub fn encode_client_state( client_state: ClientState, - code_hash: CodeHash, + checksum: Checksum, ) -> Result, Error> { let mut wasm_client_state = ics08_wasm::client_state::ClientState::::default(); - wasm_client_state.code_hash = code_hash; + wasm_client_state.checksum = checksum; wasm_client_state.data = client_state.to_any().encode_to_vec(); wasm_client_state.latest_height = client_state.latest_height(); let vec1 = wasm_client_state.to_any().encode_to_vec(); diff --git a/light-clients/ics07-tendermint-cw/src/context.rs b/light-clients/ics07-tendermint-cw/src/context.rs index ef723691a..1908daedd 100644 --- a/light-clients/ics07-tendermint-cw/src/context.rs +++ b/light-clients/ics07-tendermint-cw/src/context.rs @@ -23,7 +23,7 @@ use crate::{ use cosmwasm_std::{Deps, DepsMut, Env, Storage}; use ibc::{ core::{ - ics02_client::{error::Error, events::CodeHash}, + ics02_client::{error::Error, events::Checksum}, ics24_host::identifier::ClientId, ics26_routing::context::ReaderContext, }, @@ -39,7 +39,7 @@ pub struct Context<'a, H> { pub deps_mut: Option>, pub deps: Option>, pub env: Env, - pub code_hash: Option, + pub checksum: Option, _phantom: PhantomData, } @@ -65,11 +65,11 @@ impl<'a, H> Clone for Context<'a, H> { impl<'a, H> Context<'a, H> { pub fn new(deps: DepsMut<'a>, env: Env) -> Self { - Self { deps_mut: Some(deps), deps: None, _phantom: Default::default(), env, code_hash: None } + Self { deps_mut: Some(deps), deps: None, _phantom: Default::default(), env, checksum: None } } pub fn new_ro(deps: Deps<'a>, env: Env) -> Self { - Self { deps_mut: None, deps: Some(deps), _phantom: Default::default(), env, code_hash: None } + Self { deps_mut: None, deps: Some(deps), _phantom: Default::default(), env, checksum: None } } pub fn log(&self, msg: &str) { @@ -165,7 +165,7 @@ where use prost::Message; use tendermint_proto::Protobuf; let client_states = ReadonlyClientStates::new(self.storage()); - let code_hash = match self.code_hash.clone() { + let checksum = match self.checksum.clone() { None => { let encoded_wasm_client_state = client_states.get_prefixed(prefix).ok_or_else(|| { ContractError::Tendermint( @@ -189,12 +189,12 @@ where .to_string(), ) })?; - wasm_client_state.code_hash + wasm_client_state.checksum }, Some(x) => x, }; - let encoded = Context::::encode_client_state(client_state, code_hash).map_err(|e| { + let encoded = Context::::encode_client_state(client_state, checksum).map_err(|e| { ContractError::Tendermint(format!("error encoding client state: {:?}", e)) })?; let mut client_states = ClientStates::new(self.storage_mut()); diff --git a/light-clients/ics07-tendermint-cw/src/contract.rs b/light-clients/ics07-tendermint-cw/src/contract.rs index 204eac0c1..3020e1791 100644 --- a/light-clients/ics07-tendermint-cw/src/contract.rs +++ b/light-clients/ics07-tendermint-cw/src/contract.rs @@ -139,7 +139,7 @@ fn process_instantiate_msg( let any = Any::decode(&mut msg.consensus_state.data.as_slice())?; let consensus_state = ConsensusState::decode_vec(&any.value)?; - ctx.code_hash = Some(msg.client_state.code_hash); + ctx.checksum = Some(msg.client_state.checksum); let height = client_state.latest_height(); ctx.store_client_state(client_id.clone(), client_state) .map_err(|e| ContractError::Tendermint(e.to_string()))?; diff --git a/light-clients/ics08-wasm/src/client_def.rs b/light-clients/ics08-wasm/src/client_def.rs index e4dd8adf8..682c1166c 100644 --- a/light-clients/ics08-wasm/src/client_def.rs +++ b/light-clients/ics08-wasm/src/client_def.rs @@ -100,7 +100,7 @@ where )?; let client_state = ClientState { data: client_state.data.clone(), - code_hash: client_state.code_hash.clone(), + checksum: client_state.checksum.clone(), inner: Box::new(inner_client_state), latest_height: client_state.latest_height, _phantom: PhantomData, @@ -118,7 +118,7 @@ where .update_state_on_misbehaviour(*client_state.inner, *client_msg.inner)?; Ok(ClientState { data: client_state.data.clone(), - code_hash: client_state.code_hash.clone(), + checksum: client_state.checksum.clone(), inner: Box::new(inner_client_state), latest_height: client_state.latest_height, _phantom: PhantomData, @@ -165,7 +165,7 @@ where ClientState { inner: Box::new(client_state), data: old_client_state.data.clone(), - code_hash: old_client_state.code_hash.clone(), + checksum: old_client_state.checksum.clone(), latest_height: old_client_state.latest_height, _phantom: Default::default(), }, @@ -192,7 +192,7 @@ where )?; let client_state = ClientState { data: old_client_state.data.clone(), - code_hash: old_client_state.code_hash.clone(), + checksum: old_client_state.code_hash.clone(), inner: Box::new(inner_client_state), latest_height: old_client_state.latest_height, _phantom: PhantomData, diff --git a/light-clients/ics08-wasm/src/client_state.rs b/light-clients/ics08-wasm/src/client_state.rs index be5ee9d75..b386cc1ba 100644 --- a/light-clients/ics08-wasm/src/client_state.rs +++ b/light-clients/ics08-wasm/src/client_state.rs @@ -55,7 +55,7 @@ pub struct ClientState { pub data: Bytes, #[cfg_attr(feature = "cosmwasm", schemars(with = "String"))] #[cfg_attr(feature = "cosmwasm", serde(with = "Base64", default))] - pub code_hash: Bytes, + pub checksum: Bytes, pub latest_height: Height, #[cfg_attr(feature = "cosmwasm", serde(skip))] #[cfg_attr(feature = "cosmwasm", schemars(skip))] @@ -166,7 +166,7 @@ where let inner = AnyClientState::try_from(any).map_err(|e| e.to_string())?; Ok(Self { data: raw.data, - code_hash: raw.code_hash, + checksum: raw.checksum, inner: Box::new(inner), latest_height: raw .latest_height @@ -186,7 +186,7 @@ where fn from(client_state: ClientState) -> Self { Self { data: client_state.data, - code_hash: client_state.code_hash, + checksum: client_state.checksum, latest_height: Some(client_state.latest_height.into()), } } @@ -209,7 +209,7 @@ impl Default fn default() -> Self { ClientState { data: vec![], - code_hash: vec![], + checksum: vec![], latest_height: Default::default(), inner: Box::new(AnyClientState::default()), _phantom: Default::default(), diff --git a/light-clients/ics10-grandpa-cw/src/client.rs b/light-clients/ics10-grandpa-cw/src/client.rs index 4bb76f28f..dc8a2ba5d 100644 --- a/light-clients/ics10-grandpa-cw/src/client.rs +++ b/light-clients/ics10-grandpa-cw/src/client.rs @@ -29,7 +29,7 @@ use ibc::{ client_state::ClientType, context::{ClientKeeper, ClientReader, ClientTypes}, error::Error, - events::CodeHash, + events::Checksum, }, ics24_host::identifier::ClientId, }, @@ -176,7 +176,7 @@ impl<'a, H: HostFunctions
> ClientKeeper for Context<' client_state: Self::AnyClientState, ) -> Result<(), Error> { let client_states = ReadonlyClientStates::new(self.storage()); - let code_hash = match self.code_hash.clone() { + let checksum = match self.checksum.clone() { None => { let encoded_wasm_client_state = client_states .get() @@ -193,12 +193,12 @@ impl<'a, H: HostFunctions
> ClientKeeper for Context<' e )) })?; - wasm_client_state.code_hash + wasm_client_state.checksum }, Some(x) => x, }; - let vec1 = Self::encode_client_state(client_state, code_hash)?; + let vec1 = Self::encode_client_state(client_state, checksum)?; let mut client_state_storage = ClientStates::new(self.storage_mut()); client_state_storage.insert(vec1); Ok(()) @@ -274,11 +274,11 @@ impl<'a, H: Clone> Context<'a, H> { pub fn encode_client_state( client_state: ClientState, - code_hash: CodeHash, + checksum: Checksum, ) -> Result, Error> { let mut wasm_client_state = ics08_wasm::client_state::ClientState::::default(); - wasm_client_state.code_hash = code_hash; + wasm_client_state.checksum = checksum; wasm_client_state.data = client_state.to_any().encode_to_vec(); wasm_client_state.latest_height = client_state.latest_height(); let vec1 = wasm_client_state.to_any().encode_to_vec(); diff --git a/light-clients/ics10-grandpa-cw/src/context.rs b/light-clients/ics10-grandpa-cw/src/context.rs index 0c859f74d..779c70393 100644 --- a/light-clients/ics10-grandpa-cw/src/context.rs +++ b/light-clients/ics10-grandpa-cw/src/context.rs @@ -27,7 +27,7 @@ use cosmwasm_std::{Deps, DepsMut, Env, Storage}; use grandpa_light_client_primitives::HostFunctions; use ibc::{ core::{ - ics02_client::{error::Error, events::CodeHash}, + ics02_client::{error::Error, events::Checksum}, ics24_host::identifier::ClientId, ics26_routing::context::ReaderContext, }, @@ -44,7 +44,7 @@ pub struct Context<'a, H> { pub deps_mut: Option>, pub deps: Option>, pub env: Env, - pub code_hash: Option, + pub checksum: Option, _phantom: PhantomData, } @@ -70,11 +70,11 @@ impl<'a, H> Clone for Context<'a, H> { impl<'a, H> Context<'a, H> { pub fn new(deps: DepsMut<'a>, env: Env) -> Self { - Self { deps_mut: Some(deps), deps: None, _phantom: Default::default(), env, code_hash: None } + Self { deps_mut: Some(deps), deps: None, _phantom: Default::default(), env, checksum: None } } pub fn new_ro(deps: Deps<'a>, env: Env) -> Self { - Self { deps_mut: None, deps: Some(deps), _phantom: Default::default(), env, code_hash: None } + Self { deps_mut: None, deps: Some(deps), _phantom: Default::default(), env, checksum: None } } pub fn log(&self, msg: &str) { @@ -183,7 +183,7 @@ where use prost::Message; use tendermint_proto::Protobuf; let client_states = ReadonlyClientStates::new(self.storage()); - let code_hash = match self.code_hash.clone() { + let checksum = match self.checksum.clone() { None => { let encoded_wasm_client_state = client_states.get_prefixed(prefix).ok_or_else(|| { ContractError::Grandpa( @@ -207,11 +207,11 @@ where .to_string(), ) })?; - wasm_client_state.code_hash + wasm_client_state.checksum }, Some(x) => x, }; - let encoded = Context::::encode_client_state(client_state, code_hash) + let encoded = Context::::encode_client_state(client_state, checksum) .map_err(|e| ContractError::Grandpa(format!("error encoding client state: {:?}", e)))?; let mut client_states = ClientStates::new(self.storage_mut()); client_states.insert_prefixed(encoded, prefix); diff --git a/light-clients/ics10-grandpa-cw/src/contract.rs b/light-clients/ics10-grandpa-cw/src/contract.rs index 3425f2d2b..eb155fe09 100644 --- a/light-clients/ics10-grandpa-cw/src/contract.rs +++ b/light-clients/ics10-grandpa-cw/src/contract.rs @@ -128,7 +128,7 @@ fn process_instantiate_msg( let consensus_state = ConsensusState::decode_vec(&any.value)?; let height = client_state.latest_height(); - ctx.code_hash = Some(msg.client_state.code_hash); + ctx.checksum = Some(msg.client_state.checksum); ctx.store_client_state(client_id.clone(), client_state) .map_err(|e| ContractError::Grandpa(e.to_string()))?; ctx.store_consensus_state(client_id, height, consensus_state) From 5c4d959ec3a58bf51e450f464297aa2cc6fc28c7 Mon Sep 17 00:00:00 2001 From: Carlos Rodriguez Date: Wed, 15 Nov 2023 12:00:24 +0100 Subject: [PATCH 26/37] code_hash -> checksum --- light-clients/ics08-wasm/src/client_def.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/light-clients/ics08-wasm/src/client_def.rs b/light-clients/ics08-wasm/src/client_def.rs index 682c1166c..32d23ab00 100644 --- a/light-clients/ics08-wasm/src/client_def.rs +++ b/light-clients/ics08-wasm/src/client_def.rs @@ -192,7 +192,7 @@ where )?; let client_state = ClientState { data: old_client_state.data.clone(), - checksum: old_client_state.code_hash.clone(), + checksum: old_client_state.checksum.clone(), inner: Box::new(inner_client_state), latest_height: old_client_state.latest_height, _phantom: PhantomData, From 85a629b05e7523073e1e368c5f58805b527d2615 Mon Sep 17 00:00:00 2001 From: Carlos Rodriguez Date: Tue, 21 Nov 2023 20:45:57 +0100 Subject: [PATCH 27/37] address review comment Signed-off-by: Carlos Rodriguez --- hyperspace/core/src/macros.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hyperspace/core/src/macros.rs b/hyperspace/core/src/macros.rs index da02474ac..fff0ab73f 100644 --- a/hyperspace/core/src/macros.rs +++ b/hyperspace/core/src/macros.rs @@ -1036,7 +1036,7 @@ macro_rules! chains { } } - pub fn wasm_checksum(&self) -> Option { + pub fn wasm_checksum(&self) -> Option { let maybe_checksum = match self { $( $(#[$($meta)*])* From 979cdac8f31738e3946b54266f7188d577371d26 Mon Sep 17 00:00:00 2001 From: Steve Miskovetz Date: Tue, 21 Nov 2023 13:06:20 -0700 Subject: [PATCH 28/37] Update generated code --- utils/subxt/generated/parachain.rs | 2 +- utils/subxt/generated/src/composable/parachain.rs | 2 +- utils/subxt/generated/src/dali/parachain.rs | 2 +- utils/subxt/generated/src/default/parachain.rs | 2 +- utils/subxt/generated/src/picasso_kusama/parachain.rs | 2 +- utils/subxt/generated/src/picasso_rococo/parachain.rs | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/utils/subxt/generated/parachain.rs b/utils/subxt/generated/parachain.rs index 9217fea9f..7ad43c69d 100644 --- a/utils/subxt/generated/parachain.rs +++ b/utils/subxt/generated/parachain.rs @@ -23254,7 +23254,7 @@ pub mod api { module_id: ::std::vec::Vec<::core::primitive::u8>, }, #[codec(index = 24)] - PushWasmCode { wasm_code_id: ::std::vec::Vec<::core::primitive::u8> }, + PushWasmCode { wasm_checksum : ::std::vec::Vec<::core::primitive::u8> }, } } pub mod ics20_fee { diff --git a/utils/subxt/generated/src/composable/parachain.rs b/utils/subxt/generated/src/composable/parachain.rs index 3074ec02d..5da5147be 100644 --- a/utils/subxt/generated/src/composable/parachain.rs +++ b/utils/subxt/generated/src/composable/parachain.rs @@ -28492,7 +28492,7 @@ pub mod api { module_id: ::std::vec::Vec<::core::primitive::u8>, }, #[codec(index = 24)] - PushWasmCode { wasm_code_id: ::std::vec::Vec<::core::primitive::u8> }, + PushWasmCode { wasm_checksum : ::std::vec::Vec<::core::primitive::u8> }, } } pub mod ics20_fee { diff --git a/utils/subxt/generated/src/dali/parachain.rs b/utils/subxt/generated/src/dali/parachain.rs index 3cdeca56d..87a5b827d 100644 --- a/utils/subxt/generated/src/dali/parachain.rs +++ b/utils/subxt/generated/src/dali/parachain.rs @@ -30504,7 +30504,7 @@ pub mod api { module_id: ::std::vec::Vec<::core::primitive::u8>, }, #[codec(index = 24)] - PushWasmCode { wasm_code_id: ::std::vec::Vec<::core::primitive::u8> }, + PushWasmCode { wasm_checksum : ::std::vec::Vec<::core::primitive::u8> }, } } pub mod pallet { diff --git a/utils/subxt/generated/src/default/parachain.rs b/utils/subxt/generated/src/default/parachain.rs index d39dcee07..fb717dae3 100644 --- a/utils/subxt/generated/src/default/parachain.rs +++ b/utils/subxt/generated/src/default/parachain.rs @@ -13474,7 +13474,7 @@ pub mod api { module_id: ::std::vec::Vec<::core::primitive::u8>, }, #[codec(index = 24)] - PushWasmCode { wasm_code_id: ::std::vec::Vec<::core::primitive::u8> }, + PushWasmCode { wasm_checksum : ::std::vec::Vec<::core::primitive::u8> }, } } pub mod pallet { diff --git a/utils/subxt/generated/src/picasso_kusama/parachain.rs b/utils/subxt/generated/src/picasso_kusama/parachain.rs index 04d1f0ee0..1bf8634fb 100644 --- a/utils/subxt/generated/src/picasso_kusama/parachain.rs +++ b/utils/subxt/generated/src/picasso_kusama/parachain.rs @@ -34281,7 +34281,7 @@ pub mod api { module_id: ::std::vec::Vec<::core::primitive::u8>, }, #[codec(index = 24)] - PushWasmCode { wasm_code_id: ::std::vec::Vec<::core::primitive::u8> }, + PushWasmCode { wasm_checksum : ::std::vec::Vec<::core::primitive::u8> }, } } pub mod ics20_fee { diff --git a/utils/subxt/generated/src/picasso_rococo/parachain.rs b/utils/subxt/generated/src/picasso_rococo/parachain.rs index 04d1f0ee0..1bf8634fb 100644 --- a/utils/subxt/generated/src/picasso_rococo/parachain.rs +++ b/utils/subxt/generated/src/picasso_rococo/parachain.rs @@ -34281,7 +34281,7 @@ pub mod api { module_id: ::std::vec::Vec<::core::primitive::u8>, }, #[codec(index = 24)] - PushWasmCode { wasm_code_id: ::std::vec::Vec<::core::primitive::u8> }, + PushWasmCode { wasm_checksum : ::std::vec::Vec<::core::primitive::u8> }, } } pub mod ics20_fee { From 2214921e1dc78ee75e6585a59e95e4e53148b152 Mon Sep 17 00:00:00 2001 From: Carlos Rodriguez Date: Thu, 23 Nov 2023 00:22:32 +0100 Subject: [PATCH 29/37] refactor messages to use bytes --- .../ics07-tendermint-cw/src/contract.rs | 12 +++--- light-clients/ics07-tendermint-cw/src/msg.rs | 35 ++++++++++-------- light-clients/ics08-wasm/src/instantiate.rs | 14 +++---- .../ics10-grandpa-cw/src/contract.rs | 11 +++--- light-clients/ics10-grandpa-cw/src/msg.rs | 37 +++++++++++-------- 5 files changed, 57 insertions(+), 52 deletions(-) diff --git a/light-clients/ics07-tendermint-cw/src/contract.rs b/light-clients/ics07-tendermint-cw/src/contract.rs index 3020e1791..e27bef528 100644 --- a/light-clients/ics07-tendermint-cw/src/contract.rs +++ b/light-clients/ics07-tendermint-cw/src/contract.rs @@ -20,7 +20,7 @@ use crate::{ check_substitute_and_update_state, prune_oldest_consensus_state, verify_delay_passed, verify_upgrade_and_update_state, }, - ics23::{FakeInner, ReadonlyProcessedStates}, + ics23::ReadonlyProcessedStates, msg::{ CheckForMisbehaviourMsg, ContractResult, ExportMetadataMsg, QueryMsg, QueryResponse, StatusMsg, SudoMsg, UpdateStateMsg, UpdateStateOnMisbehaviourMsg, @@ -130,16 +130,16 @@ impl CommitValidator for HostFunctions {} impl HostFunctionsProvider for HostFunctions {} fn process_instantiate_msg( - msg: InstantiateMessage, + msg: InstantiateMessage, ctx: &mut Context, client_id: ClientId, ) -> Result { - let any = Any::decode(&mut msg.client_state.data.as_slice())?; + let any = Any::decode(&*msg.client_state)?; let client_state = ClientState::decode_vec(&any.value)?; - let any = Any::decode(&mut msg.consensus_state.data.as_slice())?; + let any = Any::decode(&*msg.consensus_state)?; let consensus_state = ConsensusState::decode_vec(&any.value)?; - ctx.checksum = Some(msg.client_state.checksum); + ctx.checksum = Some(msg.checksum); let height = client_state.latest_height(); ctx.store_client_state(client_id.clone(), client_state) .map_err(|e| ContractError::Tendermint(e.to_string()))?; @@ -159,7 +159,7 @@ pub fn instantiate( deps: DepsMut, env: Env, _info: MessageInfo, - msg: InstantiateMessage, + msg: InstantiateMessage, ) -> Result { let mut ctx = Context::::new(deps, env); let client_id = ClientId::from_str("08-wasm-0").expect("client id is valid"); diff --git a/light-clients/ics07-tendermint-cw/src/msg.rs b/light-clients/ics07-tendermint-cw/src/msg.rs index d2ce79341..4d03f23e4 100644 --- a/light-clients/ics07-tendermint-cw/src/msg.rs +++ b/light-clients/ics07-tendermint-cw/src/msg.rs @@ -159,15 +159,10 @@ pub struct MerklePath { } #[cw_serde] -pub struct ClientMessageRaw { +pub struct VerifyClientMessageRaw { #[schemars(with = "String")] #[serde(with = "Base64", default)] - pub data: Bytes, -} - -#[cw_serde] -pub struct VerifyClientMessageRaw { - pub client_message: ClientMessageRaw, + pub client_message: Bytes, } pub struct VerifyClientMessage { @@ -184,8 +179,8 @@ impl TryFrom for VerifyClientMessage { } impl VerifyClientMessage { - fn decode_client_message(raw: ClientMessageRaw) -> Result { - let any = Any::decode(raw.data.as_slice())?; + fn decode_client_message(raw: Bytes) -> Result { + let any = Any::decode(&*raw)?; let client_message = match &*any.type_url { TENDERMINT_HEADER_TYPE_URL => ClientMessage::Header(Header::decode_vec(&any.value)?), TENDERMINT_MISBEHAVIOUR_TYPE_URL => ClientMessage::Misbehaviour(Misbehaviour::decode_vec(&any.value)?), @@ -197,7 +192,9 @@ impl VerifyClientMessage { #[cw_serde] pub struct CheckForMisbehaviourMsgRaw { - pub client_message: ClientMessageRaw, + #[schemars(with = "String")] + #[serde(with = "Base64", default)] + pub client_message: Bytes, } pub struct CheckForMisbehaviourMsg { @@ -215,7 +212,9 @@ impl TryFrom for CheckForMisbehaviourMsg { #[cw_serde] pub struct UpdateStateOnMisbehaviourMsgRaw { - pub client_message: ClientMessageRaw, + #[schemars(with = "String")] + #[serde(with = "Base64", default)] + pub client_message: Bytes, } pub struct UpdateStateOnMisbehaviourMsg { @@ -233,7 +232,9 @@ impl TryFrom for UpdateStateOnMisbehaviourMsg { #[cw_serde] pub struct UpdateStateMsgRaw { - pub client_message: ClientMessageRaw, + #[schemars(with = "String")] + #[serde(with = "Base64", default)] + pub client_message: Bytes, } pub struct UpdateStateMsg { @@ -339,8 +340,12 @@ impl TryFrom for VerifyNonMembershipMsg { #[cw_serde] pub struct VerifyUpgradeAndUpdateStateMsgRaw { - pub upgrade_client_state: WasmClientState, - pub upgrade_consensus_state: WasmConsensusState, + #[schemars(with = "String")] + #[serde(with = "Base64", default)] + pub upgrade_client_state: Bytes, + #[schemars(with = "String")] + #[serde(with = "Base64", default)] + pub upgrade_consensus_state: Bytes, #[schemars(with = "String")] #[serde(with = "Base64", default)] pub proof_upgrade_client: Bytes, @@ -360,7 +365,7 @@ impl TryFrom for VerifyUpgradeAndUpdateStateM type Error = ContractError; fn try_from(raw: VerifyUpgradeAndUpdateStateMsgRaw) -> Result { - let any = Any::decode(&mut raw.upgrade_client_state.data.as_slice())?; + let any = Any::decode(&*raw.upgrade_client_state)?; let upgrade_client_state: ics07_tendermint::client_state::ClientState = ClientState::decode_vec(&any.value)?; if upgrade_client_state.trust_level != TrustThreshold::ZERO || diff --git a/light-clients/ics08-wasm/src/instantiate.rs b/light-clients/ics08-wasm/src/instantiate.rs index a06f1237d..2ee4c0027 100644 --- a/light-clients/ics08-wasm/src/instantiate.rs +++ b/light-clients/ics08-wasm/src/instantiate.rs @@ -1,16 +1,12 @@ -use super::client_state::ClientState; -use crate::consensus_state::ConsensusState; +use crate::Bytes; #[cfg(feature = "cosmwasm")] use cosmwasm_schema::cw_serde; #[cfg_attr(feature = "cosmwasm", cw_serde)] #[cfg_attr(not(feature = "cosmwasm"), derive(Clone, Debug, PartialEq))] #[derive(Eq)] -pub struct InstantiateMessage< - AnyClient: Default, - AnyClientState: Default, - AnyConsensusState: Default, -> { - pub client_state: ClientState, - pub consensus_state: ConsensusState, +pub struct InstantiateMessage { + pub client_state: Bytes, + pub consensus_state: Bytes, + pub checksum: Bytes } diff --git a/light-clients/ics10-grandpa-cw/src/contract.rs b/light-clients/ics10-grandpa-cw/src/contract.rs index eb155fe09..5193ab494 100644 --- a/light-clients/ics10-grandpa-cw/src/contract.rs +++ b/light-clients/ics10-grandpa-cw/src/contract.rs @@ -16,7 +16,6 @@ use crate::{ context::Context, error::ContractError, - ics23::FakeInner, log, msg::{ CheckForMisbehaviourMsg, @@ -118,17 +117,17 @@ impl grandpa_light_client_primitives::HostFunctions for HostFunctions { } fn process_instantiate_msg( - msg: InstantiateMessage, + msg: InstantiateMessage, ctx: &mut Context, client_id: ClientId, ) -> Result { - let any = Any::decode(&mut msg.client_state.data.as_slice())?; + let any = Any::decode(&*msg.client_state)?; let client_state = ClientState::decode_vec(&any.value)?; - let any = Any::decode(&mut msg.consensus_state.data.as_slice())?; + let any = Any::decode(&*msg.consensus_state)?; let consensus_state = ConsensusState::decode_vec(&any.value)?; let height = client_state.latest_height(); - ctx.checksum = Some(msg.client_state.checksum); + ctx.checksum = Some(msg.checksum); ctx.store_client_state(client_id.clone(), client_state) .map_err(|e| ContractError::Grandpa(e.to_string()))?; ctx.store_consensus_state(client_id, height, consensus_state) @@ -141,7 +140,7 @@ pub fn instantiate( deps: DepsMut, env: Env, _info: MessageInfo, - msg: InstantiateMessage, + msg: InstantiateMessage, ) -> Result { let mut ctx = Context::::new(deps, env); let client_id = ClientId::from_str("08-wasm-0").expect("client id is valid"); diff --git a/light-clients/ics10-grandpa-cw/src/msg.rs b/light-clients/ics10-grandpa-cw/src/msg.rs index c038fab5a..77788bbd2 100644 --- a/light-clients/ics10-grandpa-cw/src/msg.rs +++ b/light-clients/ics10-grandpa-cw/src/msg.rs @@ -178,15 +178,10 @@ pub struct MerklePath { } #[cw_serde] -pub struct ClientMessageRaw { +pub struct VerifyClientMessageRaw { #[schemars(with = "String")] #[serde(with = "Base64", default)] - pub data: Bytes, -} - -#[cw_serde] -pub struct VerifyClientMessageRaw { - pub client_message: ClientMessageRaw, + pub client_message: Bytes, } pub struct VerifyClientMessage { @@ -203,8 +198,8 @@ impl TryFrom for VerifyClientMessage { } impl VerifyClientMessage { - fn decode_client_message(raw: ClientMessageRaw) -> Result { - let any = Any::decode(raw.data.as_slice())?; + fn decode_client_message(raw: Bytes) -> Result { + let any = Any::decode(&*raw)?; let client_message = match &*any.type_url { GRANDPA_HEADER_TYPE_URL => ClientMessage::Header(Header::decode_vec(&any.value)?), GRANDPA_MISBEHAVIOUR_TYPE_URL => ClientMessage::Misbehaviour(Misbehaviour::decode_vec(&any.value)?), @@ -216,7 +211,9 @@ impl VerifyClientMessage { #[cw_serde] pub struct CheckForMisbehaviourMsgRaw { - pub client_message: ClientMessageRaw, + #[schemars(with = "String")] + #[serde(with = "Base64", default)] + pub client_message: Bytes, } pub struct CheckForMisbehaviourMsg { @@ -234,7 +231,9 @@ impl TryFrom for CheckForMisbehaviourMsg { #[cw_serde] pub struct UpdateStateOnMisbehaviourMsgRaw { - pub client_message: ClientMessageRaw, + #[schemars(with = "String")] + #[serde(with = "Base64", default)] + pub client_message: Bytes, } pub struct UpdateStateOnMisbehaviourMsg { @@ -252,7 +251,9 @@ impl TryFrom for UpdateStateOnMisbehaviourMsg { #[cw_serde] pub struct UpdateStateMsgRaw { - pub client_message: ClientMessageRaw, + #[schemars(with = "String")] + #[serde(with = "Base64", default)] + pub client_message: Bytes, } pub struct UpdateStateMsg { @@ -356,8 +357,12 @@ impl TryFrom for VerifyNonMembershipMsg { } #[cw_serde] pub struct VerifyUpgradeAndUpdateStateMsgRaw { - pub upgrade_client_state: WasmClientState, - pub upgrade_consensus_state: WasmConsensusState, + #[schemars(with = "String")] + #[serde(with = "Base64", default)] + pub upgrade_client_state: Bytes, + #[schemars(with = "String")] + #[serde(with = "Base64", default)] + pub upgrade_consensus_state: Bytes, #[schemars(with = "String")] #[serde(with = "Base64", default)] pub proof_upgrade_client: Vec, @@ -377,9 +382,9 @@ impl TryFrom for VerifyUpgradeAndUp type Error = ContractError; fn try_from(raw: VerifyUpgradeAndUpdateStateMsgRaw) -> Result { - let any = Any::decode(&mut raw.upgrade_client_state.data.as_slice())?; + let any = Any::decode(&*raw.upgrade_client_state)?; let upgrade_client_state = ClientState::decode_vec(&any.value)?; - let any = Any::decode(&mut raw.upgrade_consensus_state.data.as_slice())?; + let any = Any::decode(&*raw.upgrade_consensus_state)?; let upgrade_consensus_state = ConsensusState::decode_vec(&any.value)?; Ok(VerifyUpgradeAndUpdateStateMsg { upgrade_client_state, From 4e11055a041d91040e14b88f7e6973153fbc5242 Mon Sep 17 00:00:00 2001 From: Carlos Rodriguez Date: Thu, 23 Nov 2023 09:06:14 +0100 Subject: [PATCH 30/37] small change --- light-clients/ics07-tendermint-cw/src/contract.rs | 4 ++-- light-clients/ics07-tendermint-cw/src/msg.rs | 4 ++-- light-clients/ics10-grandpa-cw/src/contract.rs | 4 ++-- light-clients/ics10-grandpa-cw/src/msg.rs | 6 +++--- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/light-clients/ics07-tendermint-cw/src/contract.rs b/light-clients/ics07-tendermint-cw/src/contract.rs index e27bef528..393f26506 100644 --- a/light-clients/ics07-tendermint-cw/src/contract.rs +++ b/light-clients/ics07-tendermint-cw/src/contract.rs @@ -134,9 +134,9 @@ fn process_instantiate_msg( ctx: &mut Context, client_id: ClientId, ) -> Result { - let any = Any::decode(&*msg.client_state)?; + let any = Any::decode(&mut msg.client_state.as_slice())?; let client_state = ClientState::decode_vec(&any.value)?; - let any = Any::decode(&*msg.consensus_state)?; + let any = Any::decode(&mut msg.consensus_state.as_slice())?; let consensus_state = ConsensusState::decode_vec(&any.value)?; ctx.checksum = Some(msg.checksum); diff --git a/light-clients/ics07-tendermint-cw/src/msg.rs b/light-clients/ics07-tendermint-cw/src/msg.rs index 4d03f23e4..344cf0991 100644 --- a/light-clients/ics07-tendermint-cw/src/msg.rs +++ b/light-clients/ics07-tendermint-cw/src/msg.rs @@ -180,7 +180,7 @@ impl TryFrom for VerifyClientMessage { impl VerifyClientMessage { fn decode_client_message(raw: Bytes) -> Result { - let any = Any::decode(&*raw)?; + let any = Any::decode(&mut raw.as_slice())?; let client_message = match &*any.type_url { TENDERMINT_HEADER_TYPE_URL => ClientMessage::Header(Header::decode_vec(&any.value)?), TENDERMINT_MISBEHAVIOUR_TYPE_URL => ClientMessage::Misbehaviour(Misbehaviour::decode_vec(&any.value)?), @@ -365,7 +365,7 @@ impl TryFrom for VerifyUpgradeAndUpdateStateM type Error = ContractError; fn try_from(raw: VerifyUpgradeAndUpdateStateMsgRaw) -> Result { - let any = Any::decode(&*raw.upgrade_client_state)?; + let any = Any::decode(&mut raw.upgrade_client_state.as_slice())?; let upgrade_client_state: ics07_tendermint::client_state::ClientState = ClientState::decode_vec(&any.value)?; if upgrade_client_state.trust_level != TrustThreshold::ZERO || diff --git a/light-clients/ics10-grandpa-cw/src/contract.rs b/light-clients/ics10-grandpa-cw/src/contract.rs index 5193ab494..3a36bda09 100644 --- a/light-clients/ics10-grandpa-cw/src/contract.rs +++ b/light-clients/ics10-grandpa-cw/src/contract.rs @@ -121,9 +121,9 @@ fn process_instantiate_msg( ctx: &mut Context, client_id: ClientId, ) -> Result { - let any = Any::decode(&*msg.client_state)?; + let any = Any::decode(&mut msg.client_state.as_slice())?; let client_state = ClientState::decode_vec(&any.value)?; - let any = Any::decode(&*msg.consensus_state)?; + let any = Any::decode(&mut msg.consensus_state.as_slice())?; let consensus_state = ConsensusState::decode_vec(&any.value)?; let height = client_state.latest_height(); diff --git a/light-clients/ics10-grandpa-cw/src/msg.rs b/light-clients/ics10-grandpa-cw/src/msg.rs index 77788bbd2..e0c658c5d 100644 --- a/light-clients/ics10-grandpa-cw/src/msg.rs +++ b/light-clients/ics10-grandpa-cw/src/msg.rs @@ -199,7 +199,7 @@ impl TryFrom for VerifyClientMessage { impl VerifyClientMessage { fn decode_client_message(raw: Bytes) -> Result { - let any = Any::decode(&*raw)?; + let any = Any::decode(&mut raw.as_slice())?; let client_message = match &*any.type_url { GRANDPA_HEADER_TYPE_URL => ClientMessage::Header(Header::decode_vec(&any.value)?), GRANDPA_MISBEHAVIOUR_TYPE_URL => ClientMessage::Misbehaviour(Misbehaviour::decode_vec(&any.value)?), @@ -382,9 +382,9 @@ impl TryFrom for VerifyUpgradeAndUp type Error = ContractError; fn try_from(raw: VerifyUpgradeAndUpdateStateMsgRaw) -> Result { - let any = Any::decode(&*raw.upgrade_client_state)?; + let any = Any::decode(&mut raw.upgrade_client_state.as_slice())?; let upgrade_client_state = ClientState::decode_vec(&any.value)?; - let any = Any::decode(&*raw.upgrade_consensus_state)?; + let any = Any::decode(&mut raw.upgrade_consensus_state.as_slice())?; let upgrade_consensus_state = ConsensusState::decode_vec(&any.value)?; Ok(VerifyUpgradeAndUpdateStateMsg { upgrade_client_state, From 3009063341f088e5c41ed1a10d4c096422f0ee8a Mon Sep 17 00:00:00 2001 From: Carlos Rodriguez Date: Mon, 27 Nov 2023 14:55:53 +0100 Subject: [PATCH 31/37] add missing annotations --- light-clients/ics08-wasm/src/instantiate.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/light-clients/ics08-wasm/src/instantiate.rs b/light-clients/ics08-wasm/src/instantiate.rs index 2ee4c0027..18c2dacf3 100644 --- a/light-clients/ics08-wasm/src/instantiate.rs +++ b/light-clients/ics08-wasm/src/instantiate.rs @@ -6,7 +6,13 @@ use cosmwasm_schema::cw_serde; #[cfg_attr(not(feature = "cosmwasm"), derive(Clone, Debug, PartialEq))] #[derive(Eq)] pub struct InstantiateMessage { + #[schemars(with = "String")] + #[serde(with = "Base64", default)] pub client_state: Bytes, + #[schemars(with = "String")] + #[serde(with = "Base64", default)] pub consensus_state: Bytes, + #[schemars(with = "String")] + #[serde(with = "Base64", default)] pub checksum: Bytes } From 2f4a9747525b517e09864f8315e15ff35d05fc2b Mon Sep 17 00:00:00 2001 From: Carlos Rodriguez Date: Mon, 27 Nov 2023 15:03:11 +0100 Subject: [PATCH 32/37] add missing crate --- light-clients/ics08-wasm/src/instantiate.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/light-clients/ics08-wasm/src/instantiate.rs b/light-clients/ics08-wasm/src/instantiate.rs index 18c2dacf3..aeea865bb 100644 --- a/light-clients/ics08-wasm/src/instantiate.rs +++ b/light-clients/ics08-wasm/src/instantiate.rs @@ -1,4 +1,5 @@ use crate::Bytes; +use crate::msg::Base64; #[cfg(feature = "cosmwasm")] use cosmwasm_schema::cw_serde; From 884151d6bc96b1c22e8873fae9c3d3e82b928ca6 Mon Sep 17 00:00:00 2001 From: Steve Miskovetz Date: Tue, 28 Nov 2023 11:46:49 -0700 Subject: [PATCH 33/37] Use real client id --- light-clients/ics07-tendermint-cw/src/context.rs | 3 ++- light-clients/ics07-tendermint-cw/src/contract.rs | 10 +++++----- light-clients/ics07-tendermint-cw/src/msg.rs | 4 ---- light-clients/ics07-tendermint-cw/src/state.rs | 4 ++-- light-clients/ics10-grandpa-cw/src/client.rs | 3 +-- light-clients/ics10-grandpa-cw/src/context.rs | 3 ++- light-clients/ics10-grandpa-cw/src/contract.rs | 10 +++++----- light-clients/ics10-grandpa-cw/src/msg.rs | 4 ---- light-clients/ics10-grandpa-cw/src/state.rs | 4 ++-- 9 files changed, 19 insertions(+), 26 deletions(-) diff --git a/light-clients/ics07-tendermint-cw/src/context.rs b/light-clients/ics07-tendermint-cw/src/context.rs index 1908daedd..1ed0c272f 100644 --- a/light-clients/ics07-tendermint-cw/src/context.rs +++ b/light-clients/ics07-tendermint-cw/src/context.rs @@ -161,6 +161,7 @@ where &mut self, client_state: ClientState, prefix: &[u8], + client_id: ClientId, ) -> Result<(), ContractError> { use prost::Message; use tendermint_proto::Protobuf; @@ -169,7 +170,7 @@ where None => { let encoded_wasm_client_state = client_states.get_prefixed(prefix).ok_or_else(|| { ContractError::Tendermint( - Error::client_not_found(ClientId::new("x", 1).unwrap()).to_string(), + Error::client_not_found(client_id).to_string(), ) })?; let any = Any::decode(&*encoded_wasm_client_state) diff --git a/light-clients/ics07-tendermint-cw/src/contract.rs b/light-clients/ics07-tendermint-cw/src/contract.rs index 3020e1791..a52d3413c 100644 --- a/light-clients/ics07-tendermint-cw/src/contract.rs +++ b/light-clients/ics07-tendermint-cw/src/contract.rs @@ -161,8 +161,8 @@ pub fn instantiate( _info: MessageInfo, msg: InstantiateMessage, ) -> Result { + let client_id = ClientId::from_str(env.contract.address.as_str()).expect("client id is valid"); let mut ctx = Context::::new(deps, env); - let client_id = ClientId::from_str("08-wasm-0").expect("client id is valid"); let data = process_instantiate_msg(msg, &mut ctx, client_id.clone())?; let mut response = Response::default(); response.data = Some(data); @@ -175,8 +175,8 @@ pub fn sudo( msg: SudoMsg, ) -> Result { let client = TendermintClient::::default(); + let client_id = ClientId::from_str(env.contract.address.as_str()).expect("client id is valid"); let mut ctx = Context::::new(deps, env); - let client_id = ClientId::from_str("08-wasm-0").expect("client id is valid"); let data = process_message(msg, client, &mut ctx, client_id)?; let mut response = Response::default(); response.data = Some(data); @@ -244,7 +244,7 @@ fn process_message( .and_then(|(cs, cu)| { let height = cs.latest_height(); ctx.store_consensus_state_prefixed(height, cu, SUBJECT_PREFIX); - ctx.store_client_state_prefixed(cs, SUBJECT_PREFIX) + ctx.store_client_state_prefixed(cs, SUBJECT_PREFIX, client_id) .map_err(|e| ContractError::Tendermint(e.to_string()))?; Ok(to_binary(&ContractResult::success())) }), @@ -321,7 +321,7 @@ fn process_message( #[cfg_attr(not(feature = "library"), entry_point)] pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { - let client_id = ClientId::from_str("08-wasm-0").expect("client id is valid"); + let client_id = ClientId::from_str(env.contract.address.as_str()).expect("client id is valid"); match msg { QueryMsg::CheckForMisbehaviour(msg) => { let ctx = Context::::new_ro(deps, env); @@ -342,7 +342,7 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { to_binary(&QueryResponse::success().genesis_metadata(ro_proceeded_state.get_metadata())) }, QueryMsg::Status(StatusMsg {}) => { - let client_state = match get_client_state::(deps) { + let client_state = match get_client_state::(deps, client_id.clone()) { Ok(client_state) => client_state, Err(_) => return to_binary(&QueryResponse::success().status("Unknown".to_string())), }; diff --git a/light-clients/ics07-tendermint-cw/src/msg.rs b/light-clients/ics07-tendermint-cw/src/msg.rs index d2ce79341..563f8dc89 100644 --- a/light-clients/ics07-tendermint-cw/src/msg.rs +++ b/light-clients/ics07-tendermint-cw/src/msg.rs @@ -105,10 +105,6 @@ impl ContractResult { Self { heights: None } } - pub fn error(msg: String) -> Self { - Self { heights: None } - } - pub fn heights(mut self, heights: Vec) -> Self { self.heights = Some(heights); self diff --git a/light-clients/ics07-tendermint-cw/src/state.rs b/light-clients/ics07-tendermint-cw/src/state.rs index 5dcef9e59..2b7ae678f 100644 --- a/light-clients/ics07-tendermint-cw/src/state.rs +++ b/light-clients/ics07-tendermint-cw/src/state.rs @@ -25,10 +25,10 @@ use ics07_tendermint::{client_state::ClientState, consensus_state::ConsensusStat use prost::Message; /// Retrieves raw bytes from storage and deserializes them into [`ClientState`] -pub fn get_client_state(deps: Deps) -> Result, Error> { +pub fn get_client_state(deps: Deps, client_id: ClientId) -> Result, Error> { deps.storage .get(&"clientState".to_string().into_bytes()) - .ok_or_else(|| Error::unknown_client_state_type("08-wasm-0".to_string())) + .ok_or_else(|| Error::unknown_client_state_type(client_id.to_string())) .and_then(|client_state| deserialize_client_state(client_state, deps)) } diff --git a/light-clients/ics10-grandpa-cw/src/client.rs b/light-clients/ics10-grandpa-cw/src/client.rs index dc8a2ba5d..71d944023 100644 --- a/light-clients/ics10-grandpa-cw/src/client.rs +++ b/light-clients/ics10-grandpa-cw/src/client.rs @@ -20,7 +20,6 @@ use crate::{ ClientStates, ConsensusStates, FakeInner, ReadonlyClientStates, ReadonlyClients, ReadonlyConsensusStates, }, - log, }; use grandpa_light_client_primitives::HostFunctions; use ibc::{ @@ -206,7 +205,7 @@ impl<'a, H: HostFunctions
> ClientKeeper for Context<' fn store_consensus_state( &mut self, - client_id: ClientId, + _client_id: ClientId, height: Height, consensus_state: Self::AnyConsensusState, ) -> Result<(), Error> { diff --git a/light-clients/ics10-grandpa-cw/src/context.rs b/light-clients/ics10-grandpa-cw/src/context.rs index 779c70393..2909b90b6 100644 --- a/light-clients/ics10-grandpa-cw/src/context.rs +++ b/light-clients/ics10-grandpa-cw/src/context.rs @@ -179,6 +179,7 @@ where &mut self, client_state: ClientState, prefix: &[u8], + client_id: ClientId, ) -> Result<(), ContractError> { use prost::Message; use tendermint_proto::Protobuf; @@ -187,7 +188,7 @@ where None => { let encoded_wasm_client_state = client_states.get_prefixed(prefix).ok_or_else(|| { ContractError::Grandpa( - Error::client_not_found(ClientId::new("x", 1).unwrap()).to_string(), + Error::client_not_found(client_id).to_string(), ) })?; let any = Any::decode(&*encoded_wasm_client_state) diff --git a/light-clients/ics10-grandpa-cw/src/contract.rs b/light-clients/ics10-grandpa-cw/src/contract.rs index eb155fe09..7d8988e0d 100644 --- a/light-clients/ics10-grandpa-cw/src/contract.rs +++ b/light-clients/ics10-grandpa-cw/src/contract.rs @@ -143,8 +143,8 @@ pub fn instantiate( _info: MessageInfo, msg: InstantiateMessage, ) -> Result { + let client_id = ClientId::from_str(env.contract.address.as_str()).expect("client id is valid"); let mut ctx = Context::::new(deps, env); - let client_id = ClientId::from_str("08-wasm-0").expect("client id is valid"); let data = process_instantiate_msg(msg, &mut ctx, client_id.clone())?; let mut response = Response::default(); @@ -159,8 +159,8 @@ pub fn sudo( msg: SudoMsg, ) -> Result { let client = GrandpaClient::::default(); + let client_id = ClientId::from_str(env.contract.address.as_str()).expect("client id is valid"); let mut ctx = Context::::new(deps, env); - let client_id = ClientId::from_str("08-wasm-0").expect("client id is valid"); let data = process_message(msg, client, &mut ctx, client_id)?; let mut response = Response::default(); response.data = Some(data); @@ -233,7 +233,7 @@ fn process_message( let substitute_consensus_state = ctx.consensus_state_prefixed(height, SUBSTITUTE_PREFIX)?; ctx.store_consensus_state_prefixed(height, substitute_consensus_state, SUBJECT_PREFIX); - ctx.store_client_state_prefixed(substitute_client_state, SUBJECT_PREFIX) + ctx.store_client_state_prefixed(substitute_client_state, SUBJECT_PREFIX, client_id) .map_err(|e| ContractError::Grandpa(e.to_string()))?; Ok(()).map(|_| to_binary(&ContractResult::success())) @@ -295,7 +295,7 @@ fn process_message( #[cfg_attr(not(feature = "library"), entry_point)] pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { - let client_id = ClientId::from_str("08-wasm-0").expect("client id is valid"); + let client_id = ClientId::from_str(env.contract.address.as_str()).expect("client id is valid"); match msg { QueryMsg::CheckForMisbehaviour(msg) => { let ctx = Context::::new_ro(deps, env); @@ -314,7 +314,7 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { QueryMsg::ExportMetadata(ExportMetadataMsg {}) => to_binary(&QueryResponse::success().genesis_metadata(None)), QueryMsg::Status(StatusMsg {}) => { - let client_state = match get_client_state::(deps) { + let client_state = match get_client_state::(deps, client_id.clone()) { Ok(client_state) => client_state, Err(_) => return to_binary(&QueryResponse::success().status("Unknown".to_string())), }; diff --git a/light-clients/ics10-grandpa-cw/src/msg.rs b/light-clients/ics10-grandpa-cw/src/msg.rs index c038fab5a..e3b1b3fa9 100644 --- a/light-clients/ics10-grandpa-cw/src/msg.rs +++ b/light-clients/ics10-grandpa-cw/src/msg.rs @@ -105,10 +105,6 @@ impl ContractResult { Self { heights: None } } - pub fn error(msg: String) -> Self { - Self { heights: None } - } - pub fn heights(mut self, heights: Vec) -> Self { self.heights = Some(heights); self diff --git a/light-clients/ics10-grandpa-cw/src/state.rs b/light-clients/ics10-grandpa-cw/src/state.rs index 42d8da946..4720f59bc 100644 --- a/light-clients/ics10-grandpa-cw/src/state.rs +++ b/light-clients/ics10-grandpa-cw/src/state.rs @@ -25,10 +25,10 @@ use ics10_grandpa::client_state::ClientState; use prost::Message; /// Retrieves raw bytes from storage and deserializes them into [`ClientState`] -pub fn get_client_state(deps: Deps) -> Result, Error> { +pub fn get_client_state(deps: Deps, client_id: ClientId) -> Result, Error> { deps.storage .get(&"clientState".to_string().into_bytes()) - .ok_or_else(|| Error::unknown_client_state_type("08-wasm-0".to_string())) + .ok_or_else(|| Error::unknown_client_state_type(client_id.to_string())) .and_then(deserialize_client_state) } From 6beb0c96fec42eda6e845bb8bf3cd3cb19dd1911 Mon Sep 17 00:00:00 2001 From: Carlos Rodriguez Date: Mon, 4 Dec 2023 10:19:52 +0100 Subject: [PATCH 34/37] pass unwrapped client and consensus state to verify upgrade and update state for tendermint contract --- .../src/core/ics23_commitment/commitment.rs | 3 ++- .../ics07-tendermint-cw/src/helpers.rs | 20 ++++++++----------- light-clients/ics07-tendermint-cw/src/msg.rs | 17 ++++++++++------ 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/ibc/modules/src/core/ics23_commitment/commitment.rs b/ibc/modules/src/core/ics23_commitment/commitment.rs index 19b3a2f16..fe7f029e6 100644 --- a/ibc/modules/src/core/ics23_commitment/commitment.rs +++ b/ibc/modules/src/core/ics23_commitment/commitment.rs @@ -15,6 +15,7 @@ use crate::{core::ics23_commitment::error::Error, prelude::*, proofs::ProofError}; use core::{convert::TryFrom, fmt}; +use cosmwasm_schema::schemars::JsonSchema; use ibc_proto::ibc::core::commitment::v1::MerkleProof as RawMerkleProof; use serde::{Deserialize, Serialize}; use subtle_encoding::{Encoding, Hex}; @@ -61,7 +62,7 @@ impl From> for CommitmentRoot { #[derive(Clone, Debug, PartialEq)] pub struct CommitmentPath; -#[derive(Clone, PartialEq, Eq, Serialize)] +#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] #[serde(transparent)] pub struct CommitmentProofBytes { #[serde(serialize_with = "crate::serializers::ser_hex_upper")] diff --git a/light-clients/ics07-tendermint-cw/src/helpers.rs b/light-clients/ics07-tendermint-cw/src/helpers.rs index dd08707a9..b362cb440 100644 --- a/light-clients/ics07-tendermint-cw/src/helpers.rs +++ b/light-clients/ics07-tendermint-cw/src/helpers.rs @@ -98,8 +98,8 @@ pub fn verify_upgrade_and_update_state( ctx: &mut Context, client_id: ClientId, old_client_state: ClientState, - upgrade_client_state: WasmClientState, - upgrade_consensus_state: WasmConsensusState, + upgrade_client_state: ClientState, + upgrade_consensus_state: ConsensusState, proof_upgrade_client: CommitmentProofBytes, proof_upgrade_consensus_state: CommitmentProofBytes, ) -> Result<(ClientState, ConsensusState), Ics02Error> { @@ -162,21 +162,17 @@ pub fn verify_upgrade_and_update_state( ) .unwrap(); - let any = Any::decode(&mut upgrade_client_state.data.as_slice()).unwrap(); - let upgrade_client_state_inner = ClientState::::decode_vec(&any.value).unwrap(); let new_client_state = old_client_state.upgrade( - upgrade_client_state_inner.latest_height, + upgrade_client_state.latest_height, UpgradeOptions { - unbonding_period: upgrade_client_state_inner.unbonding_period, - proof_specs: upgrade_client_state_inner.proof_specs.clone(), - upgrade_path: upgrade_client_state_inner.upgrade_path.clone(), + unbonding_period: upgrade_client_state.unbonding_period, + proof_specs: upgrade_client_state.proof_specs.clone(), + upgrade_path: upgrade_client_state.upgrade_path.clone(), }, - upgrade_client_state_inner.chain_id, + upgrade_client_state.chain_id, ); - let any = Any::decode(&mut upgrade_consensus_state.data.as_slice()).unwrap(); - let upgrade_consensus_state_inner = ConsensusState::decode_vec(&any.value).unwrap(); - Ok((new_client_state, upgrade_consensus_state_inner)) + Ok((new_client_state, upgrade_consensus_state)) } pub fn check_substitute_and_update_state( diff --git a/light-clients/ics07-tendermint-cw/src/msg.rs b/light-clients/ics07-tendermint-cw/src/msg.rs index 344cf0991..ea0d13064 100644 --- a/light-clients/ics07-tendermint-cw/src/msg.rs +++ b/light-clients/ics07-tendermint-cw/src/msg.rs @@ -29,10 +29,7 @@ use ibc_proto::{google::protobuf::Any, ibc::core::client::v1::Height as HeightRa use ics07_tendermint::{ client_message::{ClientMessage, Header, Misbehaviour, TENDERMINT_HEADER_TYPE_URL, TENDERMINT_MISBEHAVIOUR_TYPE_URL}, client_state::ClientState, -}; -use ics08_wasm::{ - client_state::ClientState as WasmClientState, - consensus_state::ConsensusState as WasmConsensusState, + consensus_state::ConsensusState, }; use prost::Message; use serde::{Deserializer, Serializer}; @@ -354,9 +351,14 @@ pub struct VerifyUpgradeAndUpdateStateMsgRaw { pub proof_upgrade_consensus_state: Bytes, } +#[cw_serde] pub struct VerifyUpgradeAndUpdateStateMsg { - pub upgrade_client_state: WasmClientState, - pub upgrade_consensus_state: WasmConsensusState, + #[schemars(with = "String")] + #[serde(with = "Base64", default)] + pub upgrade_client_state: Bytes, + #[schemars(with = "String")] + #[serde(with = "Base64", default)] + pub upgrade_consensus_state: Bytes, pub proof_upgrade_client: CommitmentProofBytes, pub proof_upgrade_consensus_state: CommitmentProofBytes, } @@ -368,6 +370,9 @@ impl TryFrom for VerifyUpgradeAndUpdateStateM let any = Any::decode(&mut raw.upgrade_client_state.as_slice())?; let upgrade_client_state: ics07_tendermint::client_state::ClientState = ClientState::decode_vec(&any.value)?; + let any = Any::decode(&mut raw.upgrade_consensus_state.as_slice())?; + let upgrade_consensus_state: ics07_tendermint::consensus_state::ConsensusState = + ConsensusState::decode_vec(&any.value)?; if upgrade_client_state.trust_level != TrustThreshold::ZERO || upgrade_client_state.trusting_period != Duration::ZERO || upgrade_client_state.max_clock_drift != Duration::ZERO || From 9c885abc6406e8bef7e498451a8454a18637ad56 Mon Sep 17 00:00:00 2001 From: Carlos Rodriguez Date: Tue, 5 Dec 2023 19:38:07 +0100 Subject: [PATCH 35/37] ics07 tendermint contract should be ok now --- .../src/core/ics23_commitment/commitment.rs | 6 +++-- .../ics07-tendermint-cw/src/contract.rs | 2 +- .../ics07-tendermint-cw/src/helpers.rs | 13 +++------- light-clients/ics07-tendermint-cw/src/msg.rs | 25 +++++++------------ 4 files changed, 17 insertions(+), 29 deletions(-) diff --git a/ibc/modules/src/core/ics23_commitment/commitment.rs b/ibc/modules/src/core/ics23_commitment/commitment.rs index fe7f029e6..90d1e7390 100644 --- a/ibc/modules/src/core/ics23_commitment/commitment.rs +++ b/ibc/modules/src/core/ics23_commitment/commitment.rs @@ -15,7 +15,8 @@ use crate::{core::ics23_commitment::error::Error, prelude::*, proofs::ProofError}; use core::{convert::TryFrom, fmt}; -use cosmwasm_schema::schemars::JsonSchema; +#[cfg(feature = "cosmwasm")] +use cosmwasm_schema::schemars::{self, JsonSchema}; use ibc_proto::ibc::core::commitment::v1::MerkleProof as RawMerkleProof; use serde::{Deserialize, Serialize}; use subtle_encoding::{Encoding, Hex}; @@ -62,7 +63,8 @@ impl From> for CommitmentRoot { #[derive(Clone, Debug, PartialEq)] pub struct CommitmentPath; -#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] +#[cfg_attr(feature = "cosmwasm", derive(JsonSchema))] +#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] #[serde(transparent)] pub struct CommitmentProofBytes { #[serde(serialize_with = "crate::serializers::ser_hex_upper")] diff --git a/light-clients/ics07-tendermint-cw/src/contract.rs b/light-clients/ics07-tendermint-cw/src/contract.rs index 393f26506..02f642831 100644 --- a/light-clients/ics07-tendermint-cw/src/contract.rs +++ b/light-clients/ics07-tendermint-cw/src/contract.rs @@ -294,7 +294,7 @@ fn process_message( let old_client_state = ctx .client_state(&client_id) .map_err(|e| ContractError::Tendermint(e.to_string()))?; - let msg: VerifyUpgradeAndUpdateStateMsg = + let msg: VerifyUpgradeAndUpdateStateMsg = VerifyUpgradeAndUpdateStateMsg::try_from(msg)?; verify_upgrade_and_update_state::( ctx, diff --git a/light-clients/ics07-tendermint-cw/src/helpers.rs b/light-clients/ics07-tendermint-cw/src/helpers.rs index b362cb440..ae353146a 100644 --- a/light-clients/ics07-tendermint-cw/src/helpers.rs +++ b/light-clients/ics07-tendermint-cw/src/helpers.rs @@ -20,7 +20,7 @@ use serde::{Deserialize, Serialize}; use crate::{ context::Context, - ics23::{ConsensusStates, FakeInner, ProcessedStates}, + ics23::{ConsensusStates, ProcessedStates}, msg::SudoMsg, }; use cosmwasm_std::{to_binary, Addr, CosmosMsg, StdResult, WasmMsg}; @@ -32,12 +32,8 @@ use ibc::core::{ ics23_commitment::{commitment::CommitmentProofBytes, merkle::MerkleProof}, ics24_host::identifier::ClientId, }; -use ibc_proto::{ - google::protobuf::Any, - ibc::core::commitment::v1::{MerklePath, MerkleProof as RawMerkleProof}, -}; +use ibc_proto::ibc::core::commitment::v1::{MerklePath, MerkleProof as RawMerkleProof}; use prost::Message; -use tendermint_proto::Protobuf; use ics07_tendermint::{ client_state::{ClientState, UpgradeOptions}, @@ -46,10 +42,7 @@ use ics07_tendermint::{ HostFunctionsProvider, }; -use ics08_wasm::{ - client_state::ClientState as WasmClientState, - consensus_state::ConsensusState as WasmConsensusState, SUBJECT_PREFIX, SUBSTITUTE_PREFIX, -}; +use ics08_wasm::{SUBJECT_PREFIX, SUBSTITUTE_PREFIX}; /// CwTemplateContract is a wrapper around Addr that provides a lot of helpers /// for working with this. diff --git a/light-clients/ics07-tendermint-cw/src/msg.rs b/light-clients/ics07-tendermint-cw/src/msg.rs index ea0d13064..648cced0c 100644 --- a/light-clients/ics07-tendermint-cw/src/msg.rs +++ b/light-clients/ics07-tendermint-cw/src/msg.rs @@ -13,7 +13,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::{contract::HostFunctions, ics23::FakeInner, Bytes, ContractError}; +use crate::{Bytes, ContractError}; use core::{str::FromStr, time::Duration}; use cosmwasm_schema::cw_serde; use ibc::{ @@ -351,28 +351,21 @@ pub struct VerifyUpgradeAndUpdateStateMsgRaw { pub proof_upgrade_consensus_state: Bytes, } -#[cw_serde] -pub struct VerifyUpgradeAndUpdateStateMsg { - #[schemars(with = "String")] - #[serde(with = "Base64", default)] - pub upgrade_client_state: Bytes, - #[schemars(with = "String")] - #[serde(with = "Base64", default)] - pub upgrade_consensus_state: Bytes, +pub struct VerifyUpgradeAndUpdateStateMsg { + pub upgrade_client_state: ClientState, + pub upgrade_consensus_state: ConsensusState, pub proof_upgrade_client: CommitmentProofBytes, pub proof_upgrade_consensus_state: CommitmentProofBytes, } -impl TryFrom for VerifyUpgradeAndUpdateStateMsg { +impl TryFrom for VerifyUpgradeAndUpdateStateMsg { type Error = ContractError; fn try_from(raw: VerifyUpgradeAndUpdateStateMsgRaw) -> Result { let any = Any::decode(&mut raw.upgrade_client_state.as_slice())?; - let upgrade_client_state: ics07_tendermint::client_state::ClientState = - ClientState::decode_vec(&any.value)?; + let upgrade_client_state = ClientState::decode_vec(&any.value)?; let any = Any::decode(&mut raw.upgrade_consensus_state.as_slice())?; - let upgrade_consensus_state: ics07_tendermint::consensus_state::ConsensusState = - ConsensusState::decode_vec(&any.value)?; + let upgrade_consensus_state = ConsensusState::decode_vec(&any.value)?; if upgrade_client_state.trust_level != TrustThreshold::ZERO || upgrade_client_state.trusting_period != Duration::ZERO || upgrade_client_state.max_clock_drift != Duration::ZERO || @@ -384,8 +377,8 @@ impl TryFrom for VerifyUpgradeAndUpdateStateM } Ok(VerifyUpgradeAndUpdateStateMsg { - upgrade_client_state: raw.upgrade_client_state, - upgrade_consensus_state: raw.upgrade_consensus_state, + upgrade_client_state: upgrade_client_state, + upgrade_consensus_state: upgrade_consensus_state, proof_upgrade_client: CommitmentProofBytes::try_from(raw.proof_upgrade_client)?, proof_upgrade_consensus_state: CommitmentProofBytes::try_from( raw.proof_upgrade_consensus_state, From b4b0a02cd404214b3d3e3e756222da7d7338c960 Mon Sep 17 00:00:00 2001 From: Carlos Rodriguez Date: Mon, 11 Dec 2023 20:25:10 +0100 Subject: [PATCH 36/37] fix cargo check --- light-clients/ics08-wasm/src/instantiate.rs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/light-clients/ics08-wasm/src/instantiate.rs b/light-clients/ics08-wasm/src/instantiate.rs index aeea865bb..91c9a6d17 100644 --- a/light-clients/ics08-wasm/src/instantiate.rs +++ b/light-clients/ics08-wasm/src/instantiate.rs @@ -1,5 +1,4 @@ -use crate::Bytes; -use crate::msg::Base64; +use crate::{msg::Base64, Bytes}; #[cfg(feature = "cosmwasm")] use cosmwasm_schema::cw_serde; @@ -7,13 +6,13 @@ use cosmwasm_schema::cw_serde; #[cfg_attr(not(feature = "cosmwasm"), derive(Clone, Debug, PartialEq))] #[derive(Eq)] pub struct InstantiateMessage { - #[schemars(with = "String")] - #[serde(with = "Base64", default)] + #[cfg_attr(feature = "cosmwasm", schemars(with = "String"))] + #[cfg_attr(feature = "cosmwasm", serde(with = "Base64", default))] pub client_state: Bytes, - #[schemars(with = "String")] - #[serde(with = "Base64", default)] + #[cfg_attr(feature = "cosmwasm", schemars(with = "String"))] + #[cfg_attr(feature = "cosmwasm", serde(with = "Base64", default))] pub consensus_state: Bytes, - #[schemars(with = "String")] - #[serde(with = "Base64", default)] - pub checksum: Bytes + #[cfg_attr(feature = "cosmwasm", schemars(with = "String"))] + #[cfg_attr(feature = "cosmwasm", serde(with = "Base64", default))] + pub checksum: Bytes, } From d41fbec9bee1e3f0b26af64fa282d9116e5eb814 Mon Sep 17 00:00:00 2001 From: Carlos Rodriguez Date: Mon, 11 Dec 2023 20:25:45 +0100 Subject: [PATCH 37/37] fix linter --- contracts/pallet-ibc/src/light_clients.rs | 24 ++-- .../ics07-tendermint-cw/src/connection.rs | 2 +- .../ics07-tendermint-cw/src/context.rs | 17 ++- .../ics07-tendermint-cw/src/contract.rs | 25 ++-- .../ics07-tendermint-cw/src/error.rs | 2 +- light-clients/ics07-tendermint-cw/src/msg.rs | 24 ++-- .../ics07-tendermint-cw/src/state.rs | 5 +- light-clients/ics08-wasm/src/client_def.rs | 25 ++-- .../ics08-wasm/src/client_message.rs | 18 ++- .../ics08-wasm/src/consensus_state.rs | 3 +- light-clients/ics10-grandpa-cw/src/client.rs | 5 +- light-clients/ics10-grandpa-cw/src/context.rs | 17 ++- .../ics10-grandpa-cw/src/contract.rs | 113 ++++++++++-------- light-clients/ics10-grandpa-cw/src/error.rs | 2 +- light-clients/ics10-grandpa-cw/src/msg.rs | 17 ++- light-clients/ics10-grandpa-cw/src/state.rs | 5 +- .../generated/src/composable/parachain.rs | 2 +- .../subxt/generated/src/default/parachain.rs | 2 +- .../generated/src/picasso_kusama/parachain.rs | 2 +- .../generated/src/picasso_rococo/parachain.rs | 2 +- 20 files changed, 163 insertions(+), 149 deletions(-) diff --git a/contracts/pallet-ibc/src/light_clients.rs b/contracts/pallet-ibc/src/light_clients.rs index 6bbe179c3..60a0ba748 100644 --- a/contracts/pallet-ibc/src/light_clients.rs +++ b/contracts/pallet-ibc/src/light_clients.rs @@ -6,8 +6,7 @@ use frame_support::{ use ibc::core::{ ics02_client, ics02_client::{ - client_consensus::ConsensusState, client_message::ClientMessage, - client_state::ClientState, + client_consensus::ConsensusState, client_message::ClientMessage, client_state::ClientState, }, }; use ibc_derive::{ClientDef, ClientMessage, ClientState, ConsensusState, Protobuf}; @@ -22,10 +21,8 @@ use ics07_tendermint::{ consensus_state::TENDERMINT_CONSENSUS_STATE_TYPE_URL, }; use ics08_wasm::{ - client_message::WASM_CLIENT_MESSAGE_TYPE_URL, - client_state::WASM_CLIENT_STATE_TYPE_URL, - consensus_state::WASM_CONSENSUS_STATE_TYPE_URL, - Bytes, + client_message::WASM_CLIENT_MESSAGE_TYPE_URL, client_state::WASM_CLIENT_STATE_TYPE_URL, + consensus_state::WASM_CONSENSUS_STATE_TYPE_URL, Bytes, }; use ics10_grandpa::{ client_message::{ @@ -329,18 +326,15 @@ pub enum AnyClientMessage { impl AnyClientMessage { pub fn wasm(inner: Self) -> Result { - Ok(Self::Wasm( - ics08_wasm::client_message::ClientMessage { - data: inner.encode_to_vec()?, - inner: Box::new(inner), - } - )) + Ok(Self::Wasm(ics08_wasm::client_message::ClientMessage { + data: inner.encode_to_vec()?, + inner: Box::new(inner), + })) } pub fn unpack_recursive_into(self) -> Self { match self { - Self::Wasm(ics08_wasm::client_message::ClientMessage{inner, data}) => - *inner, + Self::Wasm(ics08_wasm::client_message::ClientMessage { inner, data }) => *inner, _ => self, } } @@ -400,7 +394,7 @@ impl From for Any { match client_msg { AnyClientMessage::Wasm(msg) => Any { type_url: WASM_CLIENT_MESSAGE_TYPE_URL.to_string(), - value: msg.encode_vec().expect("encode_vec failed") + value: msg.encode_vec().expect("encode_vec failed"), }, AnyClientMessage::Grandpa(msg) => match msg { ics10_grandpa::client_message::ClientMessage::Header(h) => Any { diff --git a/light-clients/ics07-tendermint-cw/src/connection.rs b/light-clients/ics07-tendermint-cw/src/connection.rs index ba6a4e8c6..e29b82173 100644 --- a/light-clients/ics07-tendermint-cw/src/connection.rs +++ b/light-clients/ics07-tendermint-cw/src/connection.rs @@ -50,4 +50,4 @@ impl<'a, H: HostFunctionsProvider> ConnectionReader for Context<'a, H> { "'connection_counter' is unavailable from the client".to_string(), )) } -} \ No newline at end of file +} diff --git a/light-clients/ics07-tendermint-cw/src/context.rs b/light-clients/ics07-tendermint-cw/src/context.rs index 1ed0c272f..7fecd9ba1 100644 --- a/light-clients/ics07-tendermint-cw/src/context.rs +++ b/light-clients/ics07-tendermint-cw/src/context.rs @@ -75,7 +75,7 @@ impl<'a, H> Context<'a, H> { pub fn log(&self, msg: &str) { match &self.deps_mut { Some(deps_mut) => deps_mut.api.debug(msg), - None => unimplemented!() + None => unimplemented!(), } } @@ -84,15 +84,15 @@ impl<'a, H> Context<'a, H> { Some(deps_mut) => deps_mut.storage, None => match &self.deps { Some(deps) => deps.storage, - None => unimplemented!() - } + None => unimplemented!(), + }, } } pub fn storage_mut(&mut self) -> &mut dyn Storage { match &mut self.deps_mut { Some(deps_mut) => deps_mut.storage, - None => unimplemented!() + None => unimplemented!(), } } } @@ -168,11 +168,10 @@ where let client_states = ReadonlyClientStates::new(self.storage()); let checksum = match self.checksum.clone() { None => { - let encoded_wasm_client_state = client_states.get_prefixed(prefix).ok_or_else(|| { - ContractError::Tendermint( - Error::client_not_found(client_id).to_string(), - ) - })?; + let encoded_wasm_client_state = + client_states.get_prefixed(prefix).ok_or_else(|| { + ContractError::Tendermint(Error::client_not_found(client_id).to_string()) + })?; let any = Any::decode(&*encoded_wasm_client_state) .map_err(Error::decode) .map_err(|e| ContractError::Tendermint(e.to_string()))?; diff --git a/light-clients/ics07-tendermint-cw/src/contract.rs b/light-clients/ics07-tendermint-cw/src/contract.rs index 2f1d4d543..c57cef78e 100644 --- a/light-clients/ics07-tendermint-cw/src/contract.rs +++ b/light-clients/ics07-tendermint-cw/src/contract.rs @@ -22,10 +22,9 @@ use crate::{ }, ics23::ReadonlyProcessedStates, msg::{ - CheckForMisbehaviourMsg, ContractResult, ExportMetadataMsg, QueryMsg, - QueryResponse, StatusMsg, SudoMsg, UpdateStateMsg, UpdateStateOnMisbehaviourMsg, - VerifyClientMessage, VerifyMembershipMsg, VerifyNonMembershipMsg, - VerifyUpgradeAndUpdateStateMsg, + CheckForMisbehaviourMsg, ContractResult, ExportMetadataMsg, QueryMsg, QueryResponse, + StatusMsg, SudoMsg, UpdateStateMsg, UpdateStateOnMisbehaviourMsg, VerifyClientMessage, + VerifyMembershipMsg, VerifyNonMembershipMsg, VerifyUpgradeAndUpdateStateMsg, }, state::{get_client_state, get_consensus_state}, }; @@ -169,11 +168,7 @@ pub fn instantiate( Ok(response) } #[cfg_attr(not(feature = "library"), entry_point)] -pub fn sudo( - deps: DepsMut, - env: Env, - msg: SudoMsg, -) -> Result { +pub fn sudo(deps: DepsMut, env: Env, msg: SudoMsg) -> Result { let client = TendermintClient::::default(); let client_id = ClientId::from_str(env.contract.address.as_str()).expect("client id is valid"); let mut ctx = Context::::new(deps, env); @@ -267,7 +262,7 @@ fn process_message( msg.value, ) .map_err(|e| ContractError::Tendermint(e.to_string())) - .map(|_| to_binary(&ContractResult::success())) + .map(|_| to_binary(&ContractResult::success())) }, SudoMsg::VerifyNonMembership(msg) => { let client_state = ctx @@ -357,7 +352,9 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { let tp = client_state.trusting_period.as_secs(); let now = env.block.time.seconds(); if (last_update + tp) < now { - return to_binary(&QueryResponse::success().status("Expired".to_string())) + return to_binary( + &QueryResponse::success().status("Expired".to_string()), + ) } to_binary(&QueryResponse::success().status("Active".to_string())) }, @@ -370,7 +367,11 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { let consensus_state = ctx .consensus_state(&client_id, msg.height) .map_err(|e| ContractError::Tendermint(e.to_string()))?; - to_binary(&QueryResponse::success().timestamp(consensus_state.timestamp.unix_timestamp_nanos().unsigned_abs() as u64)) + to_binary( + &QueryResponse::success().timestamp( + consensus_state.timestamp.unix_timestamp_nanos().unsigned_abs() as u64, + ), + ) }, QueryMsg::VerifyClientMessage(msg) => { let ctx = Context::::new_ro(deps, env); diff --git a/light-clients/ics07-tendermint-cw/src/error.rs b/light-clients/ics07-tendermint-cw/src/error.rs index c694db223..32541b02d 100644 --- a/light-clients/ics07-tendermint-cw/src/error.rs +++ b/light-clients/ics07-tendermint-cw/src/error.rs @@ -60,4 +60,4 @@ impl From for StdError { fn from(e: ContractError) -> Self { StdError::GenericErr { msg: e.to_string() } } -} \ No newline at end of file +} diff --git a/light-clients/ics07-tendermint-cw/src/msg.rs b/light-clients/ics07-tendermint-cw/src/msg.rs index d7267e354..ac9627401 100644 --- a/light-clients/ics07-tendermint-cw/src/msg.rs +++ b/light-clients/ics07-tendermint-cw/src/msg.rs @@ -27,7 +27,10 @@ use ibc::{ }; use ibc_proto::{google::protobuf::Any, ibc::core::client::v1::Height as HeightRaw}; use ics07_tendermint::{ - client_message::{ClientMessage, Header, Misbehaviour, TENDERMINT_HEADER_TYPE_URL, TENDERMINT_MISBEHAVIOUR_TYPE_URL}, + client_message::{ + ClientMessage, Header, Misbehaviour, TENDERMINT_HEADER_TYPE_URL, + TENDERMINT_MISBEHAVIOUR_TYPE_URL, + }, client_state::ClientState, consensus_state::ConsensusState, }; @@ -67,7 +70,13 @@ pub struct QueryResponse { impl QueryResponse { pub fn success() -> Self { - Self { is_valid: true, status: None, genesis_metadata: None, found_misbehaviour: None, timestamp: None } + Self { + is_valid: true, + status: None, + genesis_metadata: None, + found_misbehaviour: None, + timestamp: None, + } } pub fn status(mut self, status: String) -> Self { @@ -79,7 +88,7 @@ impl QueryResponse { self.genesis_metadata = genesis_metadata; self } - + pub fn misbehaviour(mut self, found_misbehavior: bool) -> Self { self.found_misbehaviour = Some(found_misbehavior); self @@ -176,7 +185,8 @@ impl VerifyClientMessage { let any = Any::decode(&mut raw.as_slice())?; let client_message = match &*any.type_url { TENDERMINT_HEADER_TYPE_URL => ClientMessage::Header(Header::decode_vec(&any.value)?), - TENDERMINT_MISBEHAVIOUR_TYPE_URL => ClientMessage::Misbehaviour(Misbehaviour::decode_vec(&any.value)?), + TENDERMINT_MISBEHAVIOUR_TYPE_URL => + ClientMessage::Misbehaviour(Misbehaviour::decode_vec(&any.value)?), _ => return Err(ContractError::Tendermint("unknown client message type".to_string())), }; Ok(client_message) @@ -361,7 +371,7 @@ impl TryFrom for VerifyUpgradeAndUp let any = Any::decode(&mut raw.upgrade_client_state.as_slice())?; let upgrade_client_state = ClientState::decode_vec(&any.value)?; let any = Any::decode(&mut raw.upgrade_consensus_state.as_slice())?; - let upgrade_consensus_state = ConsensusState::decode_vec(&any.value)?; + let upgrade_consensus_state = ConsensusState::decode_vec(&any.value)?; if upgrade_client_state.trust_level != TrustThreshold::ZERO || upgrade_client_state.trusting_period != Duration::ZERO || upgrade_client_state.max_clock_drift != Duration::ZERO || @@ -373,8 +383,8 @@ impl TryFrom for VerifyUpgradeAndUp } Ok(VerifyUpgradeAndUpdateStateMsg { - upgrade_client_state: upgrade_client_state, - upgrade_consensus_state: upgrade_consensus_state, + upgrade_client_state, + upgrade_consensus_state, proof_upgrade_client: CommitmentProofBytes::try_from(raw.proof_upgrade_client)?, proof_upgrade_consensus_state: CommitmentProofBytes::try_from( raw.proof_upgrade_consensus_state, diff --git a/light-clients/ics07-tendermint-cw/src/state.rs b/light-clients/ics07-tendermint-cw/src/state.rs index 2b7ae678f..057892a82 100644 --- a/light-clients/ics07-tendermint-cw/src/state.rs +++ b/light-clients/ics07-tendermint-cw/src/state.rs @@ -25,7 +25,10 @@ use ics07_tendermint::{client_state::ClientState, consensus_state::ConsensusStat use prost::Message; /// Retrieves raw bytes from storage and deserializes them into [`ClientState`] -pub fn get_client_state(deps: Deps, client_id: ClientId) -> Result, Error> { +pub fn get_client_state( + deps: Deps, + client_id: ClientId, +) -> Result, Error> { deps.storage .get(&"clientState".to_string().into_bytes()) .ok_or_else(|| Error::unknown_client_state_type(client_id.to_string())) diff --git a/light-clients/ics08-wasm/src/client_def.rs b/light-clients/ics08-wasm/src/client_def.rs index 32d23ab00..3725850fd 100644 --- a/light-clients/ics08-wasm/src/client_def.rs +++ b/light-clients/ics08-wasm/src/client_def.rs @@ -77,12 +77,8 @@ where client_state: Self::ClientState, client_msg: Self::ClientMessage, ) -> Result<(), Error> { - self.inner.verify_client_message( - ctx, - client_id, - *client_state.inner, - *client_msg.inner, - ) + self.inner + .verify_client_message(ctx, client_id, *client_state.inner, *client_msg.inner) } fn update_state( @@ -92,12 +88,9 @@ where client_state: Self::ClientState, client_msg: Self::ClientMessage, ) -> Result<(Self::ClientState, ConsensusUpdateResult), Error> { - let (inner_client_state, inner_consensus_update_result) = self.inner.update_state( - ctx, - client_id, - *client_state.inner, - *client_msg.inner, - )?; + let (inner_client_state, inner_consensus_update_result) = + self.inner + .update_state(ctx, client_id, *client_state.inner, *client_msg.inner)?; let client_state = ClientState { data: client_state.data.clone(), checksum: client_state.checksum.clone(), @@ -132,12 +125,8 @@ where client_state: Self::ClientState, client_msg: Self::ClientMessage, ) -> Result { - self.inner.check_for_misbehaviour( - ctx, - client_id, - *client_state.inner, - *client_msg.inner, - ) + self.inner + .check_for_misbehaviour(ctx, client_id, *client_state.inner, *client_msg.inner) } fn verify_upgrade_and_update_state( diff --git a/light-clients/ics08-wasm/src/client_message.rs b/light-clients/ics08-wasm/src/client_message.rs index 2c89ce958..42799f821 100644 --- a/light-clients/ics08-wasm/src/client_message.rs +++ b/light-clients/ics08-wasm/src/client_message.rs @@ -24,11 +24,11 @@ use core::fmt::Display; #[cfg(feature = "cosmwasm")] use cosmwasm_schema::cw_serde; use ibc::{ - core::ics02_client::client_message::ClientMessage as IbcClientMessage, - protobuf::Protobuf, + core::ics02_client::client_message::ClientMessage as IbcClientMessage, protobuf::Protobuf, +}; +use ibc_proto::{ + google::protobuf::Any, ibc::lightclients::wasm::v1::ClientMessage as RawClientMessage, }; -use ibc_proto::google::protobuf::Any; -use ibc_proto::ibc::lightclients::wasm::v1::ClientMessage as RawClientMessage; use prost::Message; pub const WASM_CLIENT_MESSAGE_TYPE_URL: &str = "/ibc.lightclients.wasm.v1.ClientMessage"; @@ -81,12 +81,10 @@ where fn try_from(raw: RawClientMessage) -> Result { let any = Any::decode(&mut &raw.data[..]) .map_err(|e| format!("failed to decode ClientMessage::data into Any: {}", e))?; - let inner = AnyClientMessage::try_from(any).map_err( - |e| { - format!("failed to decode ClientMessage::data into ClientMessage: {}", e) - })?; - Ok(Self { data: raw.data, inner: Box::new(inner)}) - + let inner = AnyClientMessage::try_from(any).map_err(|e| { + format!("failed to decode ClientMessage::data into ClientMessage: {}", e) + })?; + Ok(Self { data: raw.data, inner: Box::new(inner) }) } } diff --git a/light-clients/ics08-wasm/src/consensus_state.rs b/light-clients/ics08-wasm/src/consensus_state.rs index 9921ae23d..33dab6555 100644 --- a/light-clients/ics08-wasm/src/consensus_state.rs +++ b/light-clients/ics08-wasm/src/consensus_state.rs @@ -30,8 +30,7 @@ use cosmwasm_schema::cw_serde; use ibc::{ core::{ ics02_client::client_consensus::{ - ConsensusState as IcsConsensusState, - ConsensusState as IbcConsensusState, + ConsensusState as IcsConsensusState, ConsensusState as IbcConsensusState, }, ics23_commitment::commitment::CommitmentRoot, }, diff --git a/light-clients/ics10-grandpa-cw/src/client.rs b/light-clients/ics10-grandpa-cw/src/client.rs index 71d944023..38ee87ba6 100644 --- a/light-clients/ics10-grandpa-cw/src/client.rs +++ b/light-clients/ics10-grandpa-cw/src/client.rs @@ -70,9 +70,7 @@ impl<'a, H: HostFunctions
> ClientReader for Context<' })?; match ClientType::from_str(&data) { Err(_err) => Err(Error::unknown_client_type(data.to_string())), - Ok(val) => { - Ok(val) - }, + Ok(val) => Ok(val), } } @@ -88,7 +86,6 @@ impl<'a, H: HostFunctions
> ClientReader for Context<' client_id: &ClientId, height: Height, ) -> Result { - let consensus_states = ReadonlyConsensusStates::new(self.storage()); let value = consensus_states .get(height) diff --git a/light-clients/ics10-grandpa-cw/src/context.rs b/light-clients/ics10-grandpa-cw/src/context.rs index 2909b90b6..71ad1dce7 100644 --- a/light-clients/ics10-grandpa-cw/src/context.rs +++ b/light-clients/ics10-grandpa-cw/src/context.rs @@ -80,7 +80,7 @@ impl<'a, H> Context<'a, H> { pub fn log(&self, msg: &str) { match &self.deps_mut { Some(deps_mut) => deps_mut.api.debug(msg), - None => unimplemented!() + None => unimplemented!(), } } @@ -89,15 +89,15 @@ impl<'a, H> Context<'a, H> { Some(deps_mut) => deps_mut.storage, None => match &self.deps { Some(deps) => deps.storage, - None => unimplemented!() - } + None => unimplemented!(), + }, } } pub fn storage_mut(&mut self) -> &mut dyn Storage { match &mut self.deps_mut { Some(deps_mut) => deps_mut.storage, - None => unimplemented!() + None => unimplemented!(), } } @@ -186,11 +186,10 @@ where let client_states = ReadonlyClientStates::new(self.storage()); let checksum = match self.checksum.clone() { None => { - let encoded_wasm_client_state = client_states.get_prefixed(prefix).ok_or_else(|| { - ContractError::Grandpa( - Error::client_not_found(client_id).to_string(), - ) - })?; + let encoded_wasm_client_state = + client_states.get_prefixed(prefix).ok_or_else(|| { + ContractError::Grandpa(Error::client_not_found(client_id).to_string()) + })?; let any = Any::decode(&*encoded_wasm_client_state) .map_err(Error::decode) .map_err(|e| ContractError::Grandpa(e.to_string()))?; diff --git a/light-clients/ics10-grandpa-cw/src/contract.rs b/light-clients/ics10-grandpa-cw/src/contract.rs index f094c2d7c..8503bc5aa 100644 --- a/light-clients/ics10-grandpa-cw/src/contract.rs +++ b/light-clients/ics10-grandpa-cw/src/contract.rs @@ -18,9 +18,8 @@ use crate::{ error::ContractError, log, msg::{ - CheckForMisbehaviourMsg, - ContractResult, SudoMsg, ExportMetadataMsg, QueryMsg, QueryResponse, - StatusMsg, UpdateStateMsg, UpdateStateOnMisbehaviourMsg, VerifyClientMessage, + CheckForMisbehaviourMsg, ContractResult, ExportMetadataMsg, QueryMsg, QueryResponse, + StatusMsg, SudoMsg, UpdateStateMsg, UpdateStateOnMisbehaviourMsg, VerifyClientMessage, VerifyMembershipMsg, VerifyNonMembershipMsg, VerifyUpgradeAndUpdateStateMsg, }, state::{get_client_state, get_consensus_state}, @@ -30,7 +29,9 @@ use byteorder::{ByteOrder, LittleEndian}; use core::hash::Hasher; #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; -use cosmwasm_std::{to_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult, StdError}; +use cosmwasm_std::{ + to_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdError, StdResult, +}; use cw_storage_plus::{Item, Map}; use digest::Digest; use grandpa_light_client_primitives::justification::AncestryChain; @@ -152,11 +153,7 @@ pub fn instantiate( } #[cfg_attr(not(feature = "library"), entry_point)] -pub fn sudo( - deps: DepsMut, - env: Env, - msg: SudoMsg, -) -> Result { +pub fn sudo(deps: DepsMut, env: Env, msg: SudoMsg) -> Result { let client = GrandpaClient::::default(); let client_id = ClientId::from_str(env.contract.address.as_str()).expect("client id is valid"); let mut ctx = Context::::new(deps, env); @@ -220,7 +217,8 @@ fn process_message( }) }, SudoMsg::MigrateClientStore(_msg) => { - // load the substitute client state from the combined storage using the appropriate prefix + // load the substitute client state from the combined storage using the appropriate + // prefix let substitute_client_state = ctx .client_state_prefixed(SUBSTITUTE_PREFIX) .map_err(|e| ContractError::Grandpa(e.to_string()))?; @@ -250,7 +248,7 @@ fn process_message( msg.value, ) .map_err(|e| ContractError::Grandpa(e.to_string())) - .map(|_| to_binary(&ContractResult::success())) + .map(|_| to_binary(&ContractResult::success())) }, SudoMsg::VerifyNonMembership(msg) => { let msg = VerifyNonMembershipMsg::try_from(msg)?; @@ -324,9 +322,18 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { let height = client_state.latest_height(); match get_consensus_state(deps, &client_id, height) { Ok(consensus_state_raw) => { - let consensus_state = Context::::decode_consensus_state(&consensus_state_raw).map_err(|e|StdError::serialize_err(e.to_string(), e.to_string()))?; - if client_state.expired(core::time::Duration::from_secs(env.block.time.seconds() - consensus_state.timestamp.unix_timestamp() as u64)) { - return to_binary(&QueryResponse::success().status("Expired".to_string())); + let consensus_state = + Context::::decode_consensus_state(&consensus_state_raw) + .map_err(|e| { + StdError::serialize_err(e.to_string(), e.to_string()) + })?; + if client_state.expired(core::time::Duration::from_secs( + env.block.time.seconds() - + consensus_state.timestamp.unix_timestamp() as u64, + )) { + return to_binary( + &QueryResponse::success().status("Expired".to_string()), + ) } to_binary(&QueryResponse::success().status("Active".to_string())) }, @@ -339,7 +346,11 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { let consensus_state = ctx .consensus_state(&client_id, msg.height) .map_err(|e| ContractError::Grandpa(e.to_string()))?; - to_binary(&QueryResponse::success().timestamp(consensus_state.timestamp.unix_timestamp_nanos().unsigned_abs() as u64)) + to_binary( + &QueryResponse::success().timestamp( + consensus_state.timestamp.unix_timestamp_nanos().unsigned_abs() as u64, + ), + ) }, QueryMsg::VerifyClientMessage(msg) => { let ctx = Context::::new_ro(deps, env); @@ -456,56 +467,58 @@ pub extern "C" fn ext_hashing_twox_64_version_1(data: i64) -> i32 { out_ptr as i32 } - #[cfg(test)] mod tests { - use cosmwasm_std::from_binary; - use cosmwasm_std::testing::{mock_dependencies, mock_env}; - use tendermint::Time; + use cosmwasm_std::{ + from_binary, + testing::{mock_dependencies, mock_env}, + }; use ibc::core::ics02_client::client_state::ClientState; + use tendermint::Time; - use crate::ics23::ClientStates; + use crate::ics23::ClientStates; - use super::*; - #[test] - fn test_query() { + use super::*; + #[test] + fn test_query() { let mut deps = mock_dependencies(); - let env = mock_env(); - - - for (expected, offset) in [("Active", 0i64), ("Expired", env.block.time.seconds() as i64 - 10), ("Frozen", 0i64)] { - let mut client_state = ics10_grandpa::client_state::ClientState::::default(); - let mut consensus_state = ics10_grandpa::consensus_state::ConsensusState::new(vec![], Time::from_unix_timestamp(0, 0).unwrap()); - let height = Height { revision_number: 0, revision_height: 1000}; + let env = mock_env(); + + for (expected, offset) in + [("Active", 0i64), ("Expired", env.block.time.seconds() as i64 - 10), ("Frozen", 0i64)] + { + let mut client_state = + ics10_grandpa::client_state::ClientState::::default(); + let mut consensus_state = ics10_grandpa::consensus_state::ConsensusState::new( + vec![], + Time::from_unix_timestamp(0, 0).unwrap(), + ); + let height = Height { revision_number: 0, revision_height: 1000 }; client_state.latest_para_height = height.revision_height as _; - - consensus_state.timestamp = Time::from_unix_timestamp(env.block.time.seconds() as i64 - offset, 0).unwrap(); + consensus_state.timestamp = + Time::from_unix_timestamp(env.block.time.seconds() as i64 - offset, 0).unwrap(); let deps_mut = deps.as_mut(); if expected == "Frozen" { - let height = Height { revision_number: 0, revision_height: height.revision_height - 100}; + let height = + Height { revision_number: 0, revision_height: height.revision_height - 100 }; client_state = client_state.with_frozen_height(height.clone()).unwrap(); } - + let mut client_states = ClientStates::new(deps_mut.storage); client_states.insert(client_state.encode_to_vec().unwrap()); - + let mut context = Context::new(deps_mut, env.clone()); context.store_client_state(ClientId::default(), client_state).unwrap(); - context.store_consensus_state(ClientId::default(), height , consensus_state).unwrap(); - - let resp = query( - deps.as_ref(), - mock_env(), - QueryMsg::Status(StatusMsg{}) - ).unwrap(); - + context + .store_consensus_state(ClientId::default(), height, consensus_state) + .unwrap(); + + let resp = query(deps.as_ref(), mock_env(), QueryMsg::Status(StatusMsg {})).unwrap(); + let resp: QueryResponse = from_binary(&resp).unwrap(); - - assert_eq!( - resp, - QueryResponse::success().status(expected.to_string()) - ); + + assert_eq!(resp, QueryResponse::success().status(expected.to_string())); } - } -} \ No newline at end of file + } +} diff --git a/light-clients/ics10-grandpa-cw/src/error.rs b/light-clients/ics10-grandpa-cw/src/error.rs index 44d4baf7e..ba39107ca 100644 --- a/light-clients/ics10-grandpa-cw/src/error.rs +++ b/light-clients/ics10-grandpa-cw/src/error.rs @@ -60,4 +60,4 @@ impl From for StdError { fn from(e: ContractError) -> Self { StdError::GenericErr { msg: e.to_string() } } -} \ No newline at end of file +} diff --git a/light-clients/ics10-grandpa-cw/src/msg.rs b/light-clients/ics10-grandpa-cw/src/msg.rs index b7b27c024..13d7d0c99 100644 --- a/light-clients/ics10-grandpa-cw/src/msg.rs +++ b/light-clients/ics10-grandpa-cw/src/msg.rs @@ -30,7 +30,9 @@ use ics08_wasm::{ consensus_state::ConsensusState as WasmConsensusState, }; use ics10_grandpa::{ - client_message::{ClientMessage, Header, Misbehaviour, GRANDPA_HEADER_TYPE_URL, GRANDPA_MISBEHAVIOUR_TYPE_URL}, + client_message::{ + ClientMessage, Header, Misbehaviour, GRANDPA_HEADER_TYPE_URL, GRANDPA_MISBEHAVIOUR_TYPE_URL, + }, client_state::ClientState, consensus_state::ConsensusState, }; @@ -70,7 +72,13 @@ pub struct QueryResponse { impl QueryResponse { pub fn success() -> Self { - Self { is_valid: true, status: None, genesis_metadata: None, found_misbehaviour: None, timestamp: None } + Self { + is_valid: true, + status: None, + genesis_metadata: None, + found_misbehaviour: None, + timestamp: None, + } } pub fn status(mut self, status: String) -> Self { @@ -82,7 +90,7 @@ impl QueryResponse { self.genesis_metadata = genesis_metadata; self } - + pub fn misbehaviour(mut self, found_misbehavior: bool) -> Self { self.found_misbehaviour = Some(found_misbehavior); self @@ -198,7 +206,8 @@ impl VerifyClientMessage { let any = Any::decode(&mut raw.as_slice())?; let client_message = match &*any.type_url { GRANDPA_HEADER_TYPE_URL => ClientMessage::Header(Header::decode_vec(&any.value)?), - GRANDPA_MISBEHAVIOUR_TYPE_URL => ClientMessage::Misbehaviour(Misbehaviour::decode_vec(&any.value)?), + GRANDPA_MISBEHAVIOUR_TYPE_URL => + ClientMessage::Misbehaviour(Misbehaviour::decode_vec(&any.value)?), _ => return Err(ContractError::Grandpa("unknown client message type".to_string())), }; Ok(client_message) diff --git a/light-clients/ics10-grandpa-cw/src/state.rs b/light-clients/ics10-grandpa-cw/src/state.rs index 4720f59bc..23b9813f4 100644 --- a/light-clients/ics10-grandpa-cw/src/state.rs +++ b/light-clients/ics10-grandpa-cw/src/state.rs @@ -25,7 +25,10 @@ use ics10_grandpa::client_state::ClientState; use prost::Message; /// Retrieves raw bytes from storage and deserializes them into [`ClientState`] -pub fn get_client_state(deps: Deps, client_id: ClientId) -> Result, Error> { +pub fn get_client_state( + deps: Deps, + client_id: ClientId, +) -> Result, Error> { deps.storage .get(&"clientState".to_string().into_bytes()) .ok_or_else(|| Error::unknown_client_state_type(client_id.to_string())) diff --git a/utils/subxt/generated/src/composable/parachain.rs b/utils/subxt/generated/src/composable/parachain.rs index 5da5147be..24de0c69a 100644 --- a/utils/subxt/generated/src/composable/parachain.rs +++ b/utils/subxt/generated/src/composable/parachain.rs @@ -28492,7 +28492,7 @@ pub mod api { module_id: ::std::vec::Vec<::core::primitive::u8>, }, #[codec(index = 24)] - PushWasmCode { wasm_checksum : ::std::vec::Vec<::core::primitive::u8> }, + PushWasmCode { wasm_checksum: ::std::vec::Vec<::core::primitive::u8> }, } } pub mod ics20_fee { diff --git a/utils/subxt/generated/src/default/parachain.rs b/utils/subxt/generated/src/default/parachain.rs index fb717dae3..0a5a752c5 100644 --- a/utils/subxt/generated/src/default/parachain.rs +++ b/utils/subxt/generated/src/default/parachain.rs @@ -13474,7 +13474,7 @@ pub mod api { module_id: ::std::vec::Vec<::core::primitive::u8>, }, #[codec(index = 24)] - PushWasmCode { wasm_checksum : ::std::vec::Vec<::core::primitive::u8> }, + PushWasmCode { wasm_checksum: ::std::vec::Vec<::core::primitive::u8> }, } } pub mod pallet { diff --git a/utils/subxt/generated/src/picasso_kusama/parachain.rs b/utils/subxt/generated/src/picasso_kusama/parachain.rs index 1bf8634fb..579d5bb94 100644 --- a/utils/subxt/generated/src/picasso_kusama/parachain.rs +++ b/utils/subxt/generated/src/picasso_kusama/parachain.rs @@ -34281,7 +34281,7 @@ pub mod api { module_id: ::std::vec::Vec<::core::primitive::u8>, }, #[codec(index = 24)] - PushWasmCode { wasm_checksum : ::std::vec::Vec<::core::primitive::u8> }, + PushWasmCode { wasm_checksum: ::std::vec::Vec<::core::primitive::u8> }, } } pub mod ics20_fee { diff --git a/utils/subxt/generated/src/picasso_rococo/parachain.rs b/utils/subxt/generated/src/picasso_rococo/parachain.rs index 1bf8634fb..579d5bb94 100644 --- a/utils/subxt/generated/src/picasso_rococo/parachain.rs +++ b/utils/subxt/generated/src/picasso_rococo/parachain.rs @@ -34281,7 +34281,7 @@ pub mod api { module_id: ::std::vec::Vec<::core::primitive::u8>, }, #[codec(index = 24)] - PushWasmCode { wasm_checksum : ::std::vec::Vec<::core::primitive::u8> }, + PushWasmCode { wasm_checksum: ::std::vec::Vec<::core::primitive::u8> }, } } pub mod ics20_fee {