From 1d78333d0c12079946eee46ecc2fc4879a2f95d4 Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Fri, 13 Oct 2023 17:54:38 +0200 Subject: [PATCH 01/26] add client expiry test --- crates/ibc/Cargo.toml | 4 +- .../ics02_client/handler/update_client.rs | 67 ++++++- crates/ibc/src/mock/context.rs | 182 +++++++++++++++++- crates/ibc/src/mock/context/clients.rs | 46 ++++- 4 files changed, 292 insertions(+), 7 deletions(-) diff --git a/crates/ibc/Cargo.toml b/crates/ibc/Cargo.toml index 0a7a66025..15ff69dc2 100644 --- a/crates/ibc/Cargo.toml +++ b/crates/ibc/Cargo.toml @@ -46,7 +46,7 @@ schema = ["dep:schemars", "serde", "std"] # This feature grants access to development-time mocking libraries, such as `MockContext` or `MockHeader`. # Depends on the `testgen` suite for generating Tendermint light blocks. -mocks = ["tendermint-testgen", "tendermint/clock", "parking_lot"] +mocks = ["tendermint-testgen", "tendermint/clock", "parking_lot", "typed-builder"] [dependencies] # Proto definitions for all IBC-related interfaces, e.g., connections or channels. @@ -73,6 +73,7 @@ scale-info = { version = "2.1.2", default-features = false, features = ["derive" ## for borsh encode or decode borsh = {version = "0.10", default-features = false, optional = true } parking_lot = { version = "0.12.1", default-features = false, optional = true } +typed-builder = { version = "0.16.2", optional = true } ibc-derive = { version ="0.3.0", path = "../ibc-derive" } @@ -104,3 +105,4 @@ test-log = { version = "0.2.10", features = ["trace"] } tendermint-rpc = { version = "0.34", features = ["http-client", "websocket-client"] } tendermint-testgen = { version = "0.34" } # Needed for generating (synthetic) light blocks. parking_lot = { version = "0.12.1" } +typed-builder = { version = "0.16.2" } diff --git a/crates/ibc/src/core/ics02_client/handler/update_client.rs b/crates/ibc/src/core/ics02_client/handler/update_client.rs index 10335d7b7..32bb6ae05 100644 --- a/crates/ibc/src/core/ics02_client/handler/update_client.rs +++ b/crates/ibc/src/core/ics02_client/handler/update_client.rs @@ -121,6 +121,7 @@ where #[cfg(test)] mod tests { + use core::ops::Add; use core::str::FromStr; use core::time::Duration; @@ -143,7 +144,9 @@ mod tests { use crate::core::ics24_host::identifier::{ChainId, ClientId}; use crate::core::timestamp::Timestamp; use crate::mock::client_state::{client_type as mock_client_type, MockClientState}; - use crate::mock::context::{AnyConsensusState, MockContext}; + use crate::mock::context::{ + AnyClientState, AnyConsensusState, MockClientConfig, MockContext, MockContextConfig, + }; use crate::mock::header::MockHeader; use crate::mock::host::{HostBlock, HostType}; use crate::mock::misbehaviour::Misbehaviour as MockMisbehaviour; @@ -753,4 +756,66 @@ mod tests { assert!(res.is_ok()); ensure_misbehaviour(&ctx_a, &client_id, &tm_client_type()); } + + #[test] + fn test_expired_client() { + let remote_chain_id = ChainId::new("mockgaiaB", 1).unwrap(); + let host_chain_id = ChainId::new("mockgaiaA", 1).unwrap(); + + let remote_height = Height::new(1, 21).unwrap(); + let remote_client_height_on_host = remote_height.sub(3).unwrap(); + + let remote_client_id_on_host = ClientId::new(tm_client_type(), 0).unwrap(); + + let timestamp = Timestamp::now(); + + let mut host_ctx = MockContextConfig::builder() + .host_id(host_chain_id.clone()) + .latest_height(Height::new(1, 1).unwrap()) + .latest_timestamp(timestamp) + .build() + .with_client_config( + MockClientConfig::builder() + .client_chain_id(remote_chain_id.clone()) + .client_id(remote_client_id_on_host.clone()) + .client_state_height(remote_client_height_on_host) + .client_type(tm_client_type()) + .latest_timestamp(timestamp) + .build(), + ); + + let mut remote_ctx = MockContextConfig::builder() + .host_id(remote_chain_id.clone()) + .host_type(HostType::SyntheticTendermint) + .latest_height(remote_height) + .latest_timestamp(timestamp) + .build(); + + { + let remote_raw_client_state = host_ctx.client_state(&remote_client_id_on_host).unwrap(); + + let remote_client_state = match remote_raw_client_state { + AnyClientState::Tendermint(tm_client_state) => tm_client_state, + _ => panic!("never fails. not mock client"), + }; + + let client_trusting_period = remote_client_state.trusting_period; + + let future_timestamp = host_ctx + .host_timestamp() + .expect("never fails") + .add(client_trusting_period) + .expect("overflow"); + + host_ctx.advance_host_chain_height_with_timestamp(future_timestamp); + remote_ctx.advance_host_chain_height_with_timestamp(future_timestamp); + } + + let remote_client_state = host_ctx.client_state(&remote_client_id_on_host).unwrap(); + + assert!(remote_client_state + .status(&host_ctx, &remote_client_id_on_host) + .unwrap() + .is_expired()); + } } diff --git a/crates/ibc/src/mock/context.rs b/crates/ibc/src/mock/context.rs index f31e23a6d..9321b83b0 100644 --- a/crates/ibc/src/mock/context.rs +++ b/crates/ibc/src/mock/context.rs @@ -16,6 +16,8 @@ use parking_lot::Mutex; use tendermint_testgen::Validator as TestgenValidator; use tracing::debug; +use self::clients::TmClientStateConfig; + use super::client_state::{MOCK_CLIENT_STATE_TYPE_URL, MOCK_CLIENT_TYPE}; use super::consensus_state::MOCK_CONSENSUS_STATE_TYPE_URL; use crate::clients::ics07_tendermint::client_state::{ @@ -54,6 +56,7 @@ use crate::mock::ics18_relayer::error::RelayerError; use crate::prelude::*; use crate::signer::Signer; use crate::Height; +use typed_builder::TypedBuilder; pub const DEFAULT_BLOCK_TIME_SECS: u64 = 3; @@ -217,6 +220,100 @@ pub struct MockContext { pub logs: Vec, } +#[derive(Debug, TypedBuilder)] +#[builder(build_method(into = MockContext))] +pub struct MockContextConfig { + #[builder(default = HostType::Mock)] + host_type: HostType, + + host_id: ChainId, + + #[builder(default = Duration::from_secs(DEFAULT_BLOCK_TIME_SECS))] + block_time: Duration, + + #[builder(default = 5)] + max_history_size: usize, + + latest_height: Height, + + #[builder(default = Timestamp::now())] + latest_timestamp: Timestamp, +} + +impl From for MockContext { + fn from(params: MockContextConfig) -> Self { + assert_ne!( + params.max_history_size, 0, + "The chain must have a non-zero max_history_size" + ); + + assert_ne!( + params.latest_height.revision_height(), + 0, + "The chain must have a non-zero revision_height" + ); + + // Compute the number of blocks to store. + let n = min( + params.max_history_size as u64, + params.latest_height.revision_height(), + ); + + assert_eq!( + params.host_id.revision_number(), + params.latest_height.revision_number(), + "The version in the chain identifier must match the version in the latest height" + ); + + let next_block_timestamp = params + .latest_timestamp + .add(params.block_time) + .expect("Never fails"); + + MockContext { + host_chain_type: params.host_type, + host_chain_id: params.host_id.clone(), + max_history_size: params.max_history_size, + history: (0..n) + .rev() + .map(|i| { + // generate blocks with timestamps -> N, N - BT, N - 2BT, ... + // where N = now(), BT = block_time + HostBlock::generate_block( + params.host_id.clone(), + params.host_type, + params + .latest_height + .sub(i) + .expect("Never fails") + .revision_height(), + next_block_timestamp + .sub(params.block_time * ((i + 1) as u32)) + .expect("Never fails"), + ) + }) + .collect(), + block_time: params.block_time, + ibc_store: Arc::new(Mutex::new(MockIbcStore::default())), + events: Vec::new(), + logs: Vec::new(), + } + } +} + +#[derive(Debug, TypedBuilder)] +pub struct MockClientConfig { + client_chain_id: ChainId, + client_id: ClientId, + #[builder(default = mock_client_type())] + client_type: ClientType, + client_state_height: Height, + #[builder(default)] + consensus_state_heights: Vec, + #[builder(default = Timestamp::now())] + latest_timestamp: Timestamp, +} + /// Returns a MockContext with bare minimum initialization: no clients, no connections and no channels are /// present, and the chain has Height(5). This should be used sparingly, mostly for testing the /// creation of new domain objects. @@ -554,6 +651,81 @@ impl MockContext { self } + pub fn with_client_config(self, client: MockClientConfig) -> Self { + let cs_heights = if client.consensus_state_heights.is_empty() { + vec![client.client_state_height] + } else { + client.consensus_state_heights + }; + + let (client_state, consensus_states) = match client.client_type.as_str() { + MOCK_CLIENT_TYPE => { + let blocks: Vec<_> = cs_heights + .into_iter() + .map(|cs_height| (cs_height, MockHeader::new(cs_height))) + .collect(); + + let client_state = MockClientState::new(blocks.last().expect("never fails").1); + + let cs_states = blocks + .into_iter() + .map(|(height, block)| (height, MockConsensusState::new(block).into())) + .collect(); + + (client_state.into(), cs_states) + } + TENDERMINT_CLIENT_TYPE => { + let n_blocks = cs_heights.len(); + let blocks: Vec<_> = cs_heights + .into_iter() + .enumerate() + .map(|(i, cs_height)| { + ( + cs_height, + HostBlock::generate_tm_block( + client.client_chain_id.clone(), + cs_height.revision_height(), + client + .latest_timestamp + .sub(self.block_time * ((n_blocks - 1 - i) as u32)) + .expect("never fails"), + ), + ) + }) + .collect(); + + // TODO(rano): parametrize the other params + let client_state: TmClientState = TmClientStateConfig::builder() + .chain_id(client.client_chain_id) + .latest_height(client.client_state_height) + .build() + .try_into() + .expect("never fails"); + + client_state.validate().expect("never fails"); + + let cs_states = blocks + .into_iter() + .map(|(height, block)| (height, block.into())) + .collect(); + + (client_state.into(), cs_states) + } + _ => todo!(), + }; + + let client_record = MockClientRecord { + client_state: Some(client_state), + consensus_states, + }; + + self.ibc_store + .lock() + .clients + .insert(client.client_id.clone(), client_record); + self + } + /// Associates a connection to this context. pub fn with_connection( self, @@ -683,15 +855,17 @@ impl MockContext { /// Triggers the advancing of the host chain, by extending the history of blocks (or headers). pub fn advance_host_chain_height(&mut self) { + self.advance_host_chain_height_with_timestamp(self.host_timestamp().expect("Never fails")) + } + + /// Triggers the advancing of the host chain, by extending the history of blocks (or headers). + pub fn advance_host_chain_height_with_timestamp(&mut self, timestamp: Timestamp) { let latest_block = self.history.last().expect("history cannot be empty"); let new_block = HostBlock::generate_block( self.host_chain_id.clone(), self.host_chain_type, latest_block.height().increment().revision_height(), - latest_block - .timestamp() - .add(self.block_time) - .expect("Never fails"), + timestamp, ); // Append the new header at the tip of the history. diff --git a/crates/ibc/src/mock/context/clients.rs b/crates/ibc/src/mock/context/clients.rs index 14261184f..cac166e9e 100644 --- a/crates/ibc/src/mock/context/clients.rs +++ b/crates/ibc/src/mock/context/clients.rs @@ -1,12 +1,18 @@ //! Client context implementations for `MockContext` +use core::time::Duration; + use super::{AnyClientState, AnyConsensusState, MockClientRecord, MockContext}; +use crate::clients::ics07_tendermint::client_state::AllowUpdate; +use crate::clients::ics07_tendermint::trust_threshold::TrustThreshold; use crate::clients::ics07_tendermint::{ + client_state::ClientState as TmClientState, error::Error as TmClientError, CommonContext as TmCommonContext, ValidationContext as TmValidationContext, }; use crate::core::ics02_client::error::ClientError; use crate::core::ics02_client::{ClientExecutionContext, ClientValidationContext}; -use crate::core::ics24_host::identifier::ClientId; +use crate::core::ics23_commitment::specs::ProofSpecs; +use crate::core::ics24_host::identifier::{ChainId, ClientId}; use crate::core::ics24_host::path::{ClientConsensusStatePath, ClientStatePath}; use crate::core::timestamp::Timestamp; use crate::core::{ContextError, ValidationContext}; @@ -14,6 +20,44 @@ use crate::mock::client_state::MockClientContext; use crate::prelude::*; use crate::Height; +#[derive(typed_builder::TypedBuilder, Debug)] +pub struct TmClientStateConfig { + pub chain_id: ChainId, + #[builder(default)] + pub trust_level: TrustThreshold, + #[builder(default = Duration::from_secs(64000))] + pub trusting_period: Duration, + #[builder(default = Duration::from_secs(128000))] + pub unbonding_period: Duration, + #[builder(default = Duration::from_millis(3000))] + max_clock_drift: Duration, + pub latest_height: Height, + #[builder(default)] + pub proof_specs: ProofSpecs, + #[builder(default)] + pub upgrade_path: Vec, + #[builder(default = AllowUpdate { after_expiry: false, after_misbehaviour: false })] + allow_update: AllowUpdate, +} + +impl TryFrom for TmClientState { + type Error = TmClientError; + + fn try_from(config: TmClientStateConfig) -> Result { + TmClientState::new( + config.chain_id, + config.trust_level, + config.trusting_period, + config.unbonding_period, + config.max_clock_drift, + config.latest_height, + config.proof_specs, + config.upgrade_path, + config.allow_update, + ) + } +} + impl MockClientContext for MockContext { type ConversionError = &'static str; type AnyConsensusState = AnyConsensusState; From 90b006da23f50d6539b7d519249037659cd06867 Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Fri, 13 Oct 2023 17:56:41 +0200 Subject: [PATCH 02/26] tm hostblock supports trusted next validator set --- .../src/clients/ics07_tendermint/header.rs | 3 +- crates/ibc/src/mock/host.rs | 63 ++++++++++++++----- 2 files changed, 48 insertions(+), 18 deletions(-) diff --git a/crates/ibc/src/clients/ics07_tendermint/header.rs b/crates/ibc/src/clients/ics07_tendermint/header.rs index da0167e3e..22056d4a6 100644 --- a/crates/ibc/src/clients/ics07_tendermint/header.rs +++ b/crates/ibc/src/clients/ics07_tendermint/header.rs @@ -318,13 +318,14 @@ pub mod test_util { fn from(light_block: SyntheticTmBlock) -> Self { let SyntheticTmBlock { trusted_height, + trusted_next_validators, light_block, } = light_block; Self { signed_header: light_block.signed_header, validator_set: light_block.validators, trusted_height, - trusted_next_validator_set: light_block.next_validators, + trusted_next_validator_set: trusted_next_validators, } } } diff --git a/crates/ibc/src/mock/host.rs b/crates/ibc/src/mock/host.rs index 18950335d..4f7436cf9 100644 --- a/crates/ibc/src/mock/host.rs +++ b/crates/ibc/src/mock/host.rs @@ -6,6 +6,7 @@ use ibc_proto::google::protobuf::Any; use ibc_proto::ibc::lightclients::tendermint::v1::Header as RawHeader; use ibc_proto::protobuf::Protobuf as ErasedProtobuf; use tendermint::block::Header as TmHeader; +use tendermint::validator::Set as ValidatorSet; use tendermint_testgen::light_block::TmLightBlock; use tendermint_testgen::{ Generator, Header as TestgenHeader, LightBlock as TestgenLightBlock, @@ -38,6 +39,7 @@ pub enum HostType { #[derive(Clone, Debug, PartialEq, Eq)] pub struct SyntheticTmBlock { pub trusted_height: Height, + pub trusted_next_validators: ValidatorSet, pub light_block: TmLightBlock, } @@ -78,6 +80,15 @@ impl HostBlock { } } + pub fn set_trusted_next_validators_set(&mut self, trusted_next_validators: ValidatorSet) { + match self { + HostBlock::Mock(_) => {} + HostBlock::SyntheticTendermint(light_block) => { + light_block.trusted_next_validators = trusted_next_validators + } + } + } + /// Returns the timestamp of a block. pub fn timestamp(&self) -> Timestamp { match self { @@ -119,18 +130,23 @@ impl HostBlock { timestamp, })), HostType::SyntheticTendermint => { + let light_block = TestgenLightBlock::new_default_with_header( + TestgenHeader::new(validators) + .height(height) + .chain_id(&chain_id.to_string()) + .next_validators(next_validators) + .time(timestamp.into_tm_time().expect("Never fails")), + ) + .validators(validators) + .next_validators(next_validators) + .generate() + .expect("Never fails"); + HostBlock::SyntheticTendermint(Box::new(SyntheticTmBlock { trusted_height: Height::new(chain_id.revision_number(), 1) .expect("Never fails"), - light_block: TestgenLightBlock::new_default_with_header( - TestgenHeader::new(validators) - .height(height) - .chain_id(&chain_id.to_string()) - .next_validators(next_validators) - .time(timestamp.into_tm_time().expect("Never fails")), - ) - .generate() - .expect("Never fails"), + trusted_next_validators: light_block.next_validators.clone(), + light_block, })) } } @@ -141,15 +157,27 @@ impl HostBlock { height: u64, timestamp: Timestamp, ) -> SyntheticTmBlock { - let light_block = TestgenLightBlock::new_default_with_time_and_chain_id( - chain_id.to_string(), - timestamp.into_tm_time().expect("Never fails"), - height, - ) - .generate() - .expect("Never fails"); + // TODO(rano): use HeaderBuilder pattern + + let validators = [ + TestgenValidator::new("1").voting_power(50), + TestgenValidator::new("2").voting_power(50), + ]; + + let header = TestgenHeader::new(&validators) + .height(height) + .chain_id(chain_id.as_str()) + .next_validators(&validators) + .time(timestamp.into_tm_time().expect("Never fails")); + + let light_block = TestgenLightBlock::new_default_with_header(header) + .generate() + .expect("Never fails"); + SyntheticTmBlock { + // TODO(rano): don't use constant for rev_height trusted_height: Height::new(chain_id.revision_number(), 1).expect("Never fails"), + trusted_next_validators: light_block.next_validators.clone(), light_block, } } @@ -197,6 +225,7 @@ impl From for Any { let SyntheticTmBlock { trusted_height, + trusted_next_validators, light_block, } = light_block; @@ -204,7 +233,7 @@ impl From for Any { signed_header: Some(light_block.signed_header.into()), validator_set: Some(light_block.validators.into()), trusted_height: Some(trusted_height.into()), - trusted_validators: Some(light_block.next_validators.into()), + trusted_validators: Some(trusted_next_validators.into()), } .encode_to_vec() } From 6039366ba0e96280923d2c77e9603c185cda1dbe Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Fri, 13 Oct 2023 17:57:14 +0200 Subject: [PATCH 03/26] fix validator change update test --- .../ics02_client/handler/update_client.rs | 53 ++++++++++++++----- 1 file changed, 39 insertions(+), 14 deletions(-) diff --git a/crates/ibc/src/core/ics02_client/handler/update_client.rs b/crates/ibc/src/core/ics02_client/handler/update_client.rs index 32bb6ae05..b2599f324 100644 --- a/crates/ibc/src/core/ics02_client/handler/update_client.rs +++ b/crates/ibc/src/core/ics02_client/handler/update_client.rs @@ -252,7 +252,6 @@ mod tests { fn test_update_synthetic_tendermint_client_validator_change_ok() { let client_id = ClientId::new(tm_client_type(), 0).unwrap(); let client_height = Height::new(1, 20).unwrap(); - let update_height = Height::new(1, 21).unwrap(); let chain_id_b = ChainId::new("mockgaiaB", 1).unwrap(); let mut ctx = MockContext::new( @@ -262,6 +261,8 @@ mod tests { Height::new(1, 1).unwrap(), ) .with_client_parametrized_with_chain_id( + // client state initialized with client_height, and + // [{id: 1, power: 50}, {id: 2, power: 50}] for validator set and next validator set. chain_id_b.clone(), &client_id, client_height, @@ -269,22 +270,39 @@ mod tests { Some(client_height), ); + let ctx_b_val_history = [ + // TODO(rano): the validator set params during setups. + // Here I picked the default validator set which is + // used at host side client creation. + // + // validator set of height-20 + vec![ + TestgenValidator::new("1").voting_power(50), + TestgenValidator::new("2").voting_power(50), + ], + // validator set of height-21 + vec![ + TestgenValidator::new("1").voting_power(50), + TestgenValidator::new("2").voting_power(50), + ], + // validator set of height-22 + vec![ + TestgenValidator::new("1").voting_power(30), + TestgenValidator::new("2").voting_power(70), + ], + // validator set of height-23 + vec![ + TestgenValidator::new("1").voting_power(20), + TestgenValidator::new("2").voting_power(80), + ], + ]; + + let update_height = client_height.add(ctx_b_val_history.len() as u64 - 2); + let ctx_b = MockContext::new_with_validator_history( chain_id_b, HostType::SyntheticTendermint, - &[ - // TODO(rano): the validator set params during setups. - // Here I picked the default validator set which is - // used at host side client creation. - vec![ - TestgenValidator::new("1").voting_power(50), - TestgenValidator::new("2").voting_power(50), - ], - vec![ - TestgenValidator::new("1").voting_power(60), - TestgenValidator::new("2").voting_power(40), - ], - ], + &ctx_b_val_history, update_height, ); @@ -293,6 +311,13 @@ mod tests { let mut block = ctx_b.host_block(&update_height).unwrap().clone(); block.set_trusted_height(client_height); + let trusted_next_validator_set = match ctx_b.host_block(&client_height).expect("no error") { + HostBlock::SyntheticTendermint(header) => header.light_block.next_validators.clone(), + _ => panic!("unexpected host block type"), + }; + + block.set_trusted_next_validators_set(trusted_next_validator_set); + let latest_header_height = block.height(); let msg = MsgUpdateClient { client_id, From a2163f1cd2b4f848ae285ec26bb9f0ac0719d7b1 Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Fri, 13 Oct 2023 17:57:56 +0200 Subject: [PATCH 04/26] fix incorrect validator updates at each block --- crates/ibc/src/mock/context.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/ibc/src/mock/context.rs b/crates/ibc/src/mock/context.rs index 9321b83b0..581861f43 100644 --- a/crates/ibc/src/mock/context.rs +++ b/crates/ibc/src/mock/context.rs @@ -465,8 +465,8 @@ impl MockContext { DEFAULT_BLOCK_TIME_SECS * (i as u64 + 1), )) .expect("Never fails"), - &validator_history[i], - &validator_history[i + 1], + &validator_history[max_history_size - 1 - i], + &validator_history[max_history_size - i], ) }) .collect(); From 7dfc285bd1e4a6e8f8e1aff93c7c83c5deb96e70 Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Fri, 13 Oct 2023 17:58:26 +0200 Subject: [PATCH 05/26] add sad client update for validator change --- .../ics02_client/handler/update_client.rs | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/crates/ibc/src/core/ics02_client/handler/update_client.rs b/crates/ibc/src/core/ics02_client/handler/update_client.rs index b2599f324..996386f7e 100644 --- a/crates/ibc/src/core/ics02_client/handler/update_client.rs +++ b/crates/ibc/src/core/ics02_client/handler/update_client.rs @@ -339,6 +339,87 @@ mod tests { assert_eq!(client_state.latest_height(), latest_header_height); } + #[test] + fn test_update_synthetic_tendermint_client_validator_change_fail() { + let client_id = ClientId::new(tm_client_type(), 0).unwrap(); + let client_height = Height::new(1, 20).unwrap(); + let chain_id_b = ChainId::new("mockgaiaB", 1).unwrap(); + + let ctx = MockContext::new( + ChainId::new("mockgaiaA", 1).unwrap(), + HostType::Mock, + 5, + Height::new(1, 1).unwrap(), + ) + .with_client_parametrized_with_chain_id( + // client state initialized with client_height, and + // [{id: 1, power: 50}, {id: 2, power: 50}] for validator set and next validator set. + chain_id_b.clone(), + &client_id, + client_height, + Some(tm_client_type()), // The target host chain (B) is synthetic TM. + Some(client_height), + ); + + let ctx_b_val_history = [ + // TODO(rano): the validator set params during setups. + // Here I picked the default validator set which is + // used at host side client creation. + // + // validator set of height-20 + vec![ + TestgenValidator::new("1").voting_power(50), + TestgenValidator::new("2").voting_power(50), + ], + // incorrect next validator set for height-20 + // validator set of height-21 + vec![ + TestgenValidator::new("1").voting_power(45), + TestgenValidator::new("2").voting_power(55), + ], + // validator set of height-22 + vec![ + TestgenValidator::new("1").voting_power(30), + TestgenValidator::new("2").voting_power(70), + ], + // validator set of height-23 + vec![ + TestgenValidator::new("1").voting_power(20), + TestgenValidator::new("2").voting_power(80), + ], + ]; + + let update_height = client_height.add(ctx_b_val_history.len() as u64 - 2); + + let ctx_b = MockContext::new_with_validator_history( + chain_id_b, + HostType::SyntheticTendermint, + &ctx_b_val_history, + update_height, + ); + + let signer = get_dummy_account_id(); + + let mut block = ctx_b.host_block(&update_height).unwrap().clone(); + block.set_trusted_height(client_height); + + let trusted_next_validator_set = match ctx_b.host_block(&client_height).expect("no error") { + HostBlock::SyntheticTendermint(header) => header.light_block.next_validators.clone(), + _ => panic!("unexpected host block type"), + }; + + block.set_trusted_next_validators_set(trusted_next_validator_set); + + let msg = MsgUpdateClient { + client_id, + client_message: block.into(), + signer, + }; + + let res = validate(&ctx, MsgUpdateOrMisbehaviour::UpdateClient(msg.clone())); + assert!(res.is_err()); + } + #[test] fn test_update_synthetic_tendermint_client_non_adjacent_ok() { let client_id = ClientId::new(tm_client_type(), 0).unwrap(); From 78f5edadac43e6db89cc493ab369ae861927a0ed Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Fri, 13 Oct 2023 18:05:19 +0200 Subject: [PATCH 06/26] cargo fmt --- crates/ibc/src/mock/context.rs | 3 +-- crates/ibc/src/mock/context/clients.rs | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/crates/ibc/src/mock/context.rs b/crates/ibc/src/mock/context.rs index 581861f43..70ecb7de6 100644 --- a/crates/ibc/src/mock/context.rs +++ b/crates/ibc/src/mock/context.rs @@ -15,9 +15,9 @@ use ibc_proto::protobuf::Protobuf; use parking_lot::Mutex; use tendermint_testgen::Validator as TestgenValidator; use tracing::debug; +use typed_builder::TypedBuilder; use self::clients::TmClientStateConfig; - use super::client_state::{MOCK_CLIENT_STATE_TYPE_URL, MOCK_CLIENT_TYPE}; use super::consensus_state::MOCK_CONSENSUS_STATE_TYPE_URL; use crate::clients::ics07_tendermint::client_state::{ @@ -56,7 +56,6 @@ use crate::mock::ics18_relayer::error::RelayerError; use crate::prelude::*; use crate::signer::Signer; use crate::Height; -use typed_builder::TypedBuilder; pub const DEFAULT_BLOCK_TIME_SECS: u64 = 3; diff --git a/crates/ibc/src/mock/context/clients.rs b/crates/ibc/src/mock/context/clients.rs index cac166e9e..b79f0526e 100644 --- a/crates/ibc/src/mock/context/clients.rs +++ b/crates/ibc/src/mock/context/clients.rs @@ -3,10 +3,10 @@ use core::time::Duration; use super::{AnyClientState, AnyConsensusState, MockClientRecord, MockContext}; -use crate::clients::ics07_tendermint::client_state::AllowUpdate; +use crate::clients::ics07_tendermint::client_state::{AllowUpdate, ClientState as TmClientState}; +use crate::clients::ics07_tendermint::error::Error as TmClientError; use crate::clients::ics07_tendermint::trust_threshold::TrustThreshold; use crate::clients::ics07_tendermint::{ - client_state::ClientState as TmClientState, error::Error as TmClientError, CommonContext as TmCommonContext, ValidationContext as TmValidationContext, }; use crate::core::ics02_client::error::ClientError; From 89ffdbfffd484f637f118261532c7029304c9a0f Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Mon, 16 Oct 2023 14:46:25 +0200 Subject: [PATCH 07/26] catch up with main branch changes --- crates/ibc/src/mock/context.rs | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/crates/ibc/src/mock/context.rs b/crates/ibc/src/mock/context.rs index 70ecb7de6..0e0689854 100644 --- a/crates/ibc/src/mock/context.rs +++ b/crates/ibc/src/mock/context.rs @@ -231,7 +231,7 @@ pub struct MockContextConfig { block_time: Duration, #[builder(default = 5)] - max_history_size: usize, + max_history_size: u64, latest_height: Height, @@ -254,7 +254,7 @@ impl From for MockContext { // Compute the number of blocks to store. let n = min( - params.max_history_size as u64, + params.max_history_size, params.latest_height.revision_height(), ); @@ -420,7 +420,7 @@ impl MockContext { validator_history: &[Vec], latest_height: Height, ) -> Self { - let max_history_size = validator_history.len() - 1; + let max_history_size = validator_history.len() as u64 - 1; assert_ne!( max_history_size, 0, @@ -434,7 +434,7 @@ impl MockContext { ); assert!( - max_history_size as u64 <= latest_height.revision_height(), + max_history_size <= latest_height.revision_height(), "The number of blocks must be greater than the number of validator set histories" ); @@ -455,17 +455,12 @@ impl MockContext { HostBlock::generate_block_with_validators( host_id.clone(), host_type, - latest_height - .sub(i as u64) - .expect("Never fails") - .revision_height(), + latest_height.sub(i).expect("Never fails").revision_height(), next_block_timestamp - .sub(Duration::from_secs( - DEFAULT_BLOCK_TIME_SECS * (i as u64 + 1), - )) + .sub(Duration::from_secs(DEFAULT_BLOCK_TIME_SECS * (i + 1))) .expect("Never fails"), - &validator_history[max_history_size - 1 - i], - &validator_history[max_history_size - i], + &validator_history[(max_history_size - i) as usize - 1], + &validator_history[(max_history_size - i) as usize], ) }) .collect(); @@ -473,7 +468,7 @@ impl MockContext { MockContext { host_chain_type: host_type, host_chain_id: host_id.clone(), - max_history_size: max_history_size as u64, + max_history_size, history, block_time, ibc_store: Arc::new(Mutex::new(MockIbcStore::default())), From 2d90996f2770343818307c1e668b193b9f10f573 Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Mon, 16 Oct 2023 16:05:43 +0200 Subject: [PATCH 08/26] update MockContextConfig with validator set history --- crates/ibc/src/mock/context.rs | 41 +++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/crates/ibc/src/mock/context.rs b/crates/ibc/src/mock/context.rs index 0e0689854..f3eb725c5 100644 --- a/crates/ibc/src/mock/context.rs +++ b/crates/ibc/src/mock/context.rs @@ -233,6 +233,9 @@ pub struct MockContextConfig { #[builder(default = 5)] max_history_size: u64, + #[builder(default, setter(strip_option))] + validator_set_history: Option>>, + latest_height: Height, #[builder(default = Timestamp::now())] @@ -269,11 +272,30 @@ impl From for MockContext { .add(params.block_time) .expect("Never fails"); - MockContext { - host_chain_type: params.host_type, - host_chain_id: params.host_id.clone(), - max_history_size: params.max_history_size, - history: (0..n) + let history = if let Some(validator_set_history) = params.validator_set_history { + (0..n) + .rev() + .map(|i| { + // generate blocks with timestamps -> N, N - BT, N - 2BT, ... + // where N = now(), BT = block_time + HostBlock::generate_block_with_validators( + params.host_id.clone(), + params.host_type, + params + .latest_height + .sub(i) + .expect("Never fails") + .revision_height(), + next_block_timestamp + .sub(params.block_time * ((i + 1) as u32)) + .expect("Never fails"), + &validator_set_history[(n - i) as usize - 1], + &validator_set_history[(n - i) as usize], + ) + }) + .collect() + } else { + (0..n) .rev() .map(|i| { // generate blocks with timestamps -> N, N - BT, N - 2BT, ... @@ -291,7 +313,14 @@ impl From for MockContext { .expect("Never fails"), ) }) - .collect(), + .collect() + }; + + MockContext { + host_chain_type: params.host_type, + host_chain_id: params.host_id.clone(), + max_history_size: params.max_history_size, + history, block_time: params.block_time, ibc_store: Arc::new(Mutex::new(MockIbcStore::default())), events: Vec::new(), From ef774cc1a12c183722a3fd5ab269e309ed7e252f Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Mon, 16 Oct 2023 16:06:32 +0200 Subject: [PATCH 09/26] refactor tests with updated MockContextConfig --- .../ics02_client/handler/update_client.rs | 92 ++++++++++--------- 1 file changed, 48 insertions(+), 44 deletions(-) diff --git a/crates/ibc/src/core/ics02_client/handler/update_client.rs b/crates/ibc/src/core/ics02_client/handler/update_client.rs index 996386f7e..598f02552 100644 --- a/crates/ibc/src/core/ics02_client/handler/update_client.rs +++ b/crates/ibc/src/core/ics02_client/handler/update_client.rs @@ -254,23 +254,24 @@ mod tests { let client_height = Height::new(1, 20).unwrap(); let chain_id_b = ChainId::new("mockgaiaB", 1).unwrap(); - let mut ctx = MockContext::new( - ChainId::new("mockgaiaA", 1).unwrap(), - HostType::Mock, - 5, - Height::new(1, 1).unwrap(), - ) - .with_client_parametrized_with_chain_id( - // client state initialized with client_height, and - // [{id: 1, power: 50}, {id: 2, power: 50}] for validator set and next validator set. - chain_id_b.clone(), - &client_id, - client_height, - Some(tm_client_type()), // The target host chain (B) is synthetic TM. - Some(client_height), - ); + let mut ctx = MockContextConfig::builder() + .host_id(ChainId::new("mockgaiaA", 1).unwrap()) + .host_type(HostType::Mock) + .latest_height(Height::new(1, 1).unwrap()) + .max_history_size(5) + .build() + .with_client_config( + // client state initialized with client_height, and + // [{id: 1, power: 50}, {id: 2, power: 50}] for validator set and next validator set. + MockClientConfig::builder() + .client_chain_id(chain_id_b.clone()) + .client_id(client_id.clone()) + .client_state_height(client_height) + .client_type(tm_client_type()) + .build(), + ); - let ctx_b_val_history = [ + let ctx_b_val_history = vec![ // TODO(rano): the validator set params during setups. // Here I picked the default validator set which is // used at host side client creation. @@ -299,12 +300,13 @@ mod tests { let update_height = client_height.add(ctx_b_val_history.len() as u64 - 2); - let ctx_b = MockContext::new_with_validator_history( - chain_id_b, - HostType::SyntheticTendermint, - &ctx_b_val_history, - update_height, - ); + let ctx_b = MockContextConfig::builder() + .host_id(chain_id_b.clone()) + .host_type(HostType::SyntheticTendermint) + .latest_height(update_height) + .max_history_size(ctx_b_val_history.len() as u64 - 1) + .validator_set_history(ctx_b_val_history) + .build(); let signer = get_dummy_account_id(); @@ -345,23 +347,24 @@ mod tests { let client_height = Height::new(1, 20).unwrap(); let chain_id_b = ChainId::new("mockgaiaB", 1).unwrap(); - let ctx = MockContext::new( - ChainId::new("mockgaiaA", 1).unwrap(), - HostType::Mock, - 5, - Height::new(1, 1).unwrap(), - ) - .with_client_parametrized_with_chain_id( - // client state initialized with client_height, and - // [{id: 1, power: 50}, {id: 2, power: 50}] for validator set and next validator set. - chain_id_b.clone(), - &client_id, - client_height, - Some(tm_client_type()), // The target host chain (B) is synthetic TM. - Some(client_height), - ); + let ctx = MockContextConfig::builder() + .host_id(ChainId::new("mockgaiaA", 1).unwrap()) + .host_type(HostType::Mock) + .latest_height(Height::new(1, 1).unwrap()) + .max_history_size(5) + .build() + .with_client_config( + // client state initialized with client_height, and + // [{id: 1, power: 50}, {id: 2, power: 50}] for validator set and next validator set. + MockClientConfig::builder() + .client_chain_id(chain_id_b.clone()) + .client_id(client_id.clone()) + .client_state_height(client_height) + .client_type(tm_client_type()) + .build(), + ); - let ctx_b_val_history = [ + let ctx_b_val_history = vec![ // TODO(rano): the validator set params during setups. // Here I picked the default validator set which is // used at host side client creation. @@ -391,12 +394,13 @@ mod tests { let update_height = client_height.add(ctx_b_val_history.len() as u64 - 2); - let ctx_b = MockContext::new_with_validator_history( - chain_id_b, - HostType::SyntheticTendermint, - &ctx_b_val_history, - update_height, - ); + let ctx_b = MockContextConfig::builder() + .host_id(chain_id_b.clone()) + .host_type(HostType::SyntheticTendermint) + .latest_height(update_height) + .max_history_size(ctx_b_val_history.len() as u64 - 1) + .validator_set_history(ctx_b_val_history) + .build(); let signer = get_dummy_account_id(); From 2750e90ed4e5624218854557f4e8467b112524fb Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Mon, 16 Oct 2023 16:11:01 +0200 Subject: [PATCH 10/26] rm duplicate def of `on` --- .github/workflows/cw-check.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/cw-check.yaml b/.github/workflows/cw-check.yaml index e06e19251..ae84a64d9 100644 --- a/.github/workflows/cw-check.yaml +++ b/.github/workflows/cw-check.yaml @@ -4,8 +4,6 @@ on: paths: - .github/workflows/cw-check.yml - ci/cw-check/** - -on: push: tags: - v[0-9]+.* From 25b9b4d7af0677fc0b027e82fcb1056674d119b6 Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Mon, 16 Oct 2023 16:17:22 +0200 Subject: [PATCH 11/26] add todo for max_history_size and validator_set_history --- crates/ibc/src/mock/context.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/ibc/src/mock/context.rs b/crates/ibc/src/mock/context.rs index f3eb725c5..380b3383d 100644 --- a/crates/ibc/src/mock/context.rs +++ b/crates/ibc/src/mock/context.rs @@ -230,6 +230,8 @@ pub struct MockContextConfig { #[builder(default = Duration::from_secs(DEFAULT_BLOCK_TIME_SECS))] block_time: Duration, + // TODO(rano): make max_history_size optional + // should be default to `validator_set_history.unwrap_or(6) - 1` #[builder(default = 5)] max_history_size: u64, From f05537a3bf73828cfea92426b6a1d263991a577d Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Tue, 17 Oct 2023 14:31:49 +0200 Subject: [PATCH 12/26] consistent variable naming in tests --- .../ics02_client/handler/update_client.rs | 44 +++++++++---------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/crates/ibc/src/core/ics02_client/handler/update_client.rs b/crates/ibc/src/core/ics02_client/handler/update_client.rs index 598f02552..d42751f59 100644 --- a/crates/ibc/src/core/ics02_client/handler/update_client.rs +++ b/crates/ibc/src/core/ics02_client/handler/update_client.rs @@ -869,62 +869,60 @@ mod tests { #[test] fn test_expired_client() { - let remote_chain_id = ChainId::new("mockgaiaB", 1).unwrap(); - let host_chain_id = ChainId::new("mockgaiaA", 1).unwrap(); + let chain_id_a = ChainId::new("mockgaiaA", 1).unwrap(); + let chain_id_b = ChainId::new("mockgaiaB", 1).unwrap(); - let remote_height = Height::new(1, 21).unwrap(); - let remote_client_height_on_host = remote_height.sub(3).unwrap(); + let update_height = Height::new(1, 21).unwrap(); + let client_height = update_height.sub(3).unwrap(); - let remote_client_id_on_host = ClientId::new(tm_client_type(), 0).unwrap(); + let client_id_b = ClientId::new(tm_client_type(), 0).unwrap(); let timestamp = Timestamp::now(); - let mut host_ctx = MockContextConfig::builder() - .host_id(host_chain_id.clone()) + let mut ctx_a = MockContextConfig::builder() + .host_id(chain_id_a.clone()) .latest_height(Height::new(1, 1).unwrap()) .latest_timestamp(timestamp) .build() .with_client_config( MockClientConfig::builder() - .client_chain_id(remote_chain_id.clone()) - .client_id(remote_client_id_on_host.clone()) - .client_state_height(remote_client_height_on_host) + .client_chain_id(chain_id_b.clone()) + .client_id(client_id_b.clone()) + .client_state_height(client_height) .client_type(tm_client_type()) .latest_timestamp(timestamp) .build(), ); - let mut remote_ctx = MockContextConfig::builder() - .host_id(remote_chain_id.clone()) + let mut ctx_b = MockContextConfig::builder() + .host_id(chain_id_b.clone()) .host_type(HostType::SyntheticTendermint) - .latest_height(remote_height) + .latest_height(update_height) .latest_timestamp(timestamp) .build(); { - let remote_raw_client_state = host_ctx.client_state(&remote_client_id_on_host).unwrap(); - - let remote_client_state = match remote_raw_client_state { + let client_state = match ctx_a.client_state(&client_id_b).unwrap() { AnyClientState::Tendermint(tm_client_state) => tm_client_state, _ => panic!("never fails. not mock client"), }; - let client_trusting_period = remote_client_state.trusting_period; + let client_trusting_period = client_state.trusting_period; - let future_timestamp = host_ctx + let future_timestamp = ctx_a .host_timestamp() .expect("never fails") .add(client_trusting_period) .expect("overflow"); - host_ctx.advance_host_chain_height_with_timestamp(future_timestamp); - remote_ctx.advance_host_chain_height_with_timestamp(future_timestamp); + ctx_a.advance_host_chain_height_with_timestamp(future_timestamp); + ctx_b.advance_host_chain_height_with_timestamp(future_timestamp); } - let remote_client_state = host_ctx.client_state(&remote_client_id_on_host).unwrap(); + let client_state = ctx_a.client_state(&client_id_b).unwrap(); - assert!(remote_client_state - .status(&host_ctx, &remote_client_id_on_host) + assert!(client_state + .status(&ctx_a, &client_id_b) .unwrap() .is_expired()); } From e82706793a316941f91de7879cd68f8695b8e63f Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Tue, 17 Oct 2023 14:34:12 +0200 Subject: [PATCH 13/26] bump typed-builder version --- crates/ibc/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/ibc/Cargo.toml b/crates/ibc/Cargo.toml index 15ff69dc2..231e43e1d 100644 --- a/crates/ibc/Cargo.toml +++ b/crates/ibc/Cargo.toml @@ -73,7 +73,7 @@ scale-info = { version = "2.1.2", default-features = false, features = ["derive" ## for borsh encode or decode borsh = {version = "0.10", default-features = false, optional = true } parking_lot = { version = "0.12.1", default-features = false, optional = true } -typed-builder = { version = "0.16.2", optional = true } +typed-builder = { version = "0.17.0", optional = true } ibc-derive = { version ="0.3.0", path = "../ibc-derive" } @@ -105,4 +105,4 @@ test-log = { version = "0.2.10", features = ["trace"] } tendermint-rpc = { version = "0.34", features = ["http-client", "websocket-client"] } tendermint-testgen = { version = "0.34" } # Needed for generating (synthetic) light blocks. parking_lot = { version = "0.12.1" } -typed-builder = { version = "0.16.2" } +typed-builder = { version = "0.17.0" } From bf55a977b89173f9d6f2e535e4164b9bf8fb98f0 Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Tue, 17 Oct 2023 14:37:13 +0200 Subject: [PATCH 14/26] rm redundant builder arguments --- crates/ibc/src/core/ics02_client/handler/update_client.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/crates/ibc/src/core/ics02_client/handler/update_client.rs b/crates/ibc/src/core/ics02_client/handler/update_client.rs index d42751f59..0d31edabe 100644 --- a/crates/ibc/src/core/ics02_client/handler/update_client.rs +++ b/crates/ibc/src/core/ics02_client/handler/update_client.rs @@ -256,9 +256,7 @@ mod tests { let mut ctx = MockContextConfig::builder() .host_id(ChainId::new("mockgaiaA", 1).unwrap()) - .host_type(HostType::Mock) .latest_height(Height::new(1, 1).unwrap()) - .max_history_size(5) .build() .with_client_config( // client state initialized with client_height, and @@ -349,9 +347,7 @@ mod tests { let ctx = MockContextConfig::builder() .host_id(ChainId::new("mockgaiaA", 1).unwrap()) - .host_type(HostType::Mock) .latest_height(Height::new(1, 1).unwrap()) - .max_history_size(5) .build() .with_client_config( // client state initialized with client_height, and From 87196d30e1caf5e4d1f2a06f840f2a7874de6057 Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Tue, 17 Oct 2023 14:39:13 +0200 Subject: [PATCH 15/26] replace todo with panic --- crates/ibc/src/mock/context.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ibc/src/mock/context.rs b/crates/ibc/src/mock/context.rs index 380b3383d..b3a4fe182 100644 --- a/crates/ibc/src/mock/context.rs +++ b/crates/ibc/src/mock/context.rs @@ -736,7 +736,7 @@ impl MockContext { (client_state.into(), cs_states) } - _ => todo!(), + _ => panic!("unknown client type"), }; let client_record = MockClientRecord { From 122a5707da400b7866fc5a0e6dd16f4d27ba4a0a Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Tue, 17 Oct 2023 14:51:31 +0200 Subject: [PATCH 16/26] mv Tendermint ClientStateConfig under ics07 --- .../clients/ics07_tendermint/client_state.rs | 41 ++++++++++++++++- crates/ibc/src/mock/context.rs | 2 +- crates/ibc/src/mock/context/clients.rs | 46 +------------------ 3 files changed, 42 insertions(+), 47 deletions(-) diff --git a/crates/ibc/src/clients/ics07_tendermint/client_state.rs b/crates/ibc/src/clients/ics07_tendermint/client_state.rs index cc7c1f66a..7fc11d421 100644 --- a/crates/ibc/src/clients/ics07_tendermint/client_state.rs +++ b/crates/ibc/src/clients/ics07_tendermint/client_state.rs @@ -1129,7 +1129,8 @@ pub mod test_util { use tendermint::block::Header; use crate::clients::ics07_tendermint::client_state::{AllowUpdate, ClientState}; - use crate::clients::ics07_tendermint::error::Error; + use crate::clients::ics07_tendermint::error::{Error as ClientError, Error}; + use crate::clients::ics07_tendermint::trust_threshold::TrustThreshold; use crate::core::ics02_client::height::Height; use crate::core::ics23_commitment::specs::ProofSpecs; use crate::core::ics24_host::identifier::ChainId; @@ -1180,4 +1181,42 @@ pub mod test_util { allow_update_after_misbehaviour: false, } } + + #[derive(typed_builder::TypedBuilder, Debug)] + pub struct ClientStateConfig { + pub chain_id: ChainId, + #[builder(default)] + pub trust_level: TrustThreshold, + #[builder(default = Duration::from_secs(64000))] + pub trusting_period: Duration, + #[builder(default = Duration::from_secs(128000))] + pub unbonding_period: Duration, + #[builder(default = Duration::from_millis(3000))] + max_clock_drift: Duration, + pub latest_height: Height, + #[builder(default)] + pub proof_specs: ProofSpecs, + #[builder(default)] + pub upgrade_path: Vec, + #[builder(default = AllowUpdate { after_expiry: false, after_misbehaviour: false })] + allow_update: AllowUpdate, + } + + impl TryFrom for ClientState { + type Error = ClientError; + + fn try_from(config: ClientStateConfig) -> Result { + ClientState::new( + config.chain_id, + config.trust_level, + config.trusting_period, + config.unbonding_period, + config.max_clock_drift, + config.latest_height, + config.proof_specs, + config.upgrade_path, + config.allow_update, + ) + } + } } diff --git a/crates/ibc/src/mock/context.rs b/crates/ibc/src/mock/context.rs index b3a4fe182..742b9ccf2 100644 --- a/crates/ibc/src/mock/context.rs +++ b/crates/ibc/src/mock/context.rs @@ -17,9 +17,9 @@ use tendermint_testgen::Validator as TestgenValidator; use tracing::debug; use typed_builder::TypedBuilder; -use self::clients::TmClientStateConfig; use super::client_state::{MOCK_CLIENT_STATE_TYPE_URL, MOCK_CLIENT_TYPE}; use super::consensus_state::MOCK_CONSENSUS_STATE_TYPE_URL; +use crate::clients::ics07_tendermint::client_state::test_util::ClientStateConfig as TmClientStateConfig; use crate::clients::ics07_tendermint::client_state::{ ClientState as TmClientState, TENDERMINT_CLIENT_STATE_TYPE_URL, }; diff --git a/crates/ibc/src/mock/context/clients.rs b/crates/ibc/src/mock/context/clients.rs index b79f0526e..14261184f 100644 --- a/crates/ibc/src/mock/context/clients.rs +++ b/crates/ibc/src/mock/context/clients.rs @@ -1,18 +1,12 @@ //! Client context implementations for `MockContext` -use core::time::Duration; - use super::{AnyClientState, AnyConsensusState, MockClientRecord, MockContext}; -use crate::clients::ics07_tendermint::client_state::{AllowUpdate, ClientState as TmClientState}; -use crate::clients::ics07_tendermint::error::Error as TmClientError; -use crate::clients::ics07_tendermint::trust_threshold::TrustThreshold; use crate::clients::ics07_tendermint::{ CommonContext as TmCommonContext, ValidationContext as TmValidationContext, }; use crate::core::ics02_client::error::ClientError; use crate::core::ics02_client::{ClientExecutionContext, ClientValidationContext}; -use crate::core::ics23_commitment::specs::ProofSpecs; -use crate::core::ics24_host::identifier::{ChainId, ClientId}; +use crate::core::ics24_host::identifier::ClientId; use crate::core::ics24_host::path::{ClientConsensusStatePath, ClientStatePath}; use crate::core::timestamp::Timestamp; use crate::core::{ContextError, ValidationContext}; @@ -20,44 +14,6 @@ use crate::mock::client_state::MockClientContext; use crate::prelude::*; use crate::Height; -#[derive(typed_builder::TypedBuilder, Debug)] -pub struct TmClientStateConfig { - pub chain_id: ChainId, - #[builder(default)] - pub trust_level: TrustThreshold, - #[builder(default = Duration::from_secs(64000))] - pub trusting_period: Duration, - #[builder(default = Duration::from_secs(128000))] - pub unbonding_period: Duration, - #[builder(default = Duration::from_millis(3000))] - max_clock_drift: Duration, - pub latest_height: Height, - #[builder(default)] - pub proof_specs: ProofSpecs, - #[builder(default)] - pub upgrade_path: Vec, - #[builder(default = AllowUpdate { after_expiry: false, after_misbehaviour: false })] - allow_update: AllowUpdate, -} - -impl TryFrom for TmClientState { - type Error = TmClientError; - - fn try_from(config: TmClientStateConfig) -> Result { - TmClientState::new( - config.chain_id, - config.trust_level, - config.trusting_period, - config.unbonding_period, - config.max_clock_drift, - config.latest_height, - config.proof_specs, - config.upgrade_path, - config.allow_update, - ) - } -} - impl MockClientContext for MockContext { type ConversionError = &'static str; type AnyConsensusState = AnyConsensusState; From 7f7f79f78d034cefaf296c4c31e256e4caeb0cb4 Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Tue, 17 Oct 2023 15:04:47 +0200 Subject: [PATCH 17/26] use ctx_a with ctx_b instead of only ctx --- .../ics02_client/handler/update_client.rs | 47 +++++++++++-------- 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/crates/ibc/src/core/ics02_client/handler/update_client.rs b/crates/ibc/src/core/ics02_client/handler/update_client.rs index 0d31edabe..193c3595e 100644 --- a/crates/ibc/src/core/ics02_client/handler/update_client.rs +++ b/crates/ibc/src/core/ics02_client/handler/update_client.rs @@ -206,7 +206,7 @@ mod tests { let update_height = Height::new(1, 21).unwrap(); let chain_id_b = ChainId::new("mockgaiaB", 1).unwrap(); - let mut ctx = MockContext::new( + let mut ctx_a = MockContext::new( ChainId::new("mockgaiaA", 1).unwrap(), HostType::Mock, 5, @@ -234,15 +234,18 @@ mod tests { signer, }; - let res = validate(&ctx, MsgUpdateOrMisbehaviour::UpdateClient(msg.clone())); + let res = validate(&ctx_a, MsgUpdateOrMisbehaviour::UpdateClient(msg.clone())); assert!(res.is_ok()); - let res = execute(&mut ctx, MsgUpdateOrMisbehaviour::UpdateClient(msg.clone())); + let res = execute( + &mut ctx_a, + MsgUpdateOrMisbehaviour::UpdateClient(msg.clone()), + ); assert!(res.is_ok(), "result: {res:?}"); - let client_state = ctx.client_state(&msg.client_id).unwrap(); + let client_state = ctx_a.client_state(&msg.client_id).unwrap(); assert!(client_state - .status(&ctx, &msg.client_id) + .status(&ctx_a, &msg.client_id) .unwrap() .is_active()); assert_eq!(client_state.latest_height(), latest_header_height); @@ -254,7 +257,7 @@ mod tests { let client_height = Height::new(1, 20).unwrap(); let chain_id_b = ChainId::new("mockgaiaB", 1).unwrap(); - let mut ctx = MockContextConfig::builder() + let mut ctx_a = MockContextConfig::builder() .host_id(ChainId::new("mockgaiaA", 1).unwrap()) .latest_height(Height::new(1, 1).unwrap()) .build() @@ -325,15 +328,18 @@ mod tests { signer, }; - let res = validate(&ctx, MsgUpdateOrMisbehaviour::UpdateClient(msg.clone())); + let res = validate(&ctx_a, MsgUpdateOrMisbehaviour::UpdateClient(msg.clone())); assert!(res.is_ok()); - let res = execute(&mut ctx, MsgUpdateOrMisbehaviour::UpdateClient(msg.clone())); + let res = execute( + &mut ctx_a, + MsgUpdateOrMisbehaviour::UpdateClient(msg.clone()), + ); assert!(res.is_ok(), "result: {res:?}"); - let client_state = ctx.client_state(&msg.client_id).unwrap(); + let client_state = ctx_a.client_state(&msg.client_id).unwrap(); assert!(client_state - .status(&ctx, &msg.client_id) + .status(&ctx_a, &msg.client_id) .unwrap() .is_active()); assert_eq!(client_state.latest_height(), latest_header_height); @@ -345,7 +351,7 @@ mod tests { let client_height = Height::new(1, 20).unwrap(); let chain_id_b = ChainId::new("mockgaiaB", 1).unwrap(); - let ctx = MockContextConfig::builder() + let ctx_a = MockContextConfig::builder() .host_id(ChainId::new("mockgaiaA", 1).unwrap()) .latest_height(Height::new(1, 1).unwrap()) .build() @@ -416,7 +422,7 @@ mod tests { signer, }; - let res = validate(&ctx, MsgUpdateOrMisbehaviour::UpdateClient(msg.clone())); + let res = validate(&ctx_a, MsgUpdateOrMisbehaviour::UpdateClient(msg.clone())); assert!(res.is_err()); } @@ -427,7 +433,7 @@ mod tests { let update_height = Height::new(1, 21).unwrap(); let chain_id_b = ChainId::new("mockgaiaB", 1).unwrap(); - let mut ctx = MockContext::new( + let mut ctx_a = MockContext::new( ChainId::new("mockgaiaA", 1).unwrap(), HostType::Mock, 5, @@ -456,15 +462,18 @@ mod tests { signer, }; - let res = validate(&ctx, MsgUpdateOrMisbehaviour::UpdateClient(msg.clone())); + let res = validate(&ctx_a, MsgUpdateOrMisbehaviour::UpdateClient(msg.clone())); assert!(res.is_ok()); - let res = execute(&mut ctx, MsgUpdateOrMisbehaviour::UpdateClient(msg.clone())); + let res = execute( + &mut ctx_a, + MsgUpdateOrMisbehaviour::UpdateClient(msg.clone()), + ); assert!(res.is_ok(), "result: {res:?}"); - let client_state = ctx.client_state(&msg.client_id).unwrap(); + let client_state = ctx_a.client_state(&msg.client_id).unwrap(); assert!(client_state - .status(&ctx, &msg.client_id) + .status(&ctx_a, &msg.client_id) .unwrap() .is_active()); assert_eq!(client_state.latest_height(), latest_header_height); @@ -604,7 +613,7 @@ mod tests { let chain_start_height = Height::new(1, 11).unwrap(); - let ctx = MockContext::new( + let ctx_a = MockContext::new( ChainId::new("mockgaiaA", 1).unwrap(), HostType::Mock, 5, @@ -634,7 +643,7 @@ mod tests { signer, }; - let res = validate(&ctx, MsgUpdateOrMisbehaviour::UpdateClient(msg)); + let res = validate(&ctx_a, MsgUpdateOrMisbehaviour::UpdateClient(msg)); assert!(res.is_err()); } From eb8798c2ac37f327e46a6a6cbd382324ecccd84b Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Tue, 17 Oct 2023 15:05:09 +0200 Subject: [PATCH 18/26] use client_id consistently --- .../src/core/ics02_client/handler/update_client.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/crates/ibc/src/core/ics02_client/handler/update_client.rs b/crates/ibc/src/core/ics02_client/handler/update_client.rs index 193c3595e..7b4bd990f 100644 --- a/crates/ibc/src/core/ics02_client/handler/update_client.rs +++ b/crates/ibc/src/core/ics02_client/handler/update_client.rs @@ -874,25 +874,24 @@ mod tests { #[test] fn test_expired_client() { - let chain_id_a = ChainId::new("mockgaiaA", 1).unwrap(); let chain_id_b = ChainId::new("mockgaiaB", 1).unwrap(); let update_height = Height::new(1, 21).unwrap(); let client_height = update_height.sub(3).unwrap(); - let client_id_b = ClientId::new(tm_client_type(), 0).unwrap(); + let client_id = ClientId::new(tm_client_type(), 0).unwrap(); let timestamp = Timestamp::now(); let mut ctx_a = MockContextConfig::builder() - .host_id(chain_id_a.clone()) + .host_id(ChainId::new("mockgaiaA", 1).unwrap()) .latest_height(Height::new(1, 1).unwrap()) .latest_timestamp(timestamp) .build() .with_client_config( MockClientConfig::builder() .client_chain_id(chain_id_b.clone()) - .client_id(client_id_b.clone()) + .client_id(client_id.clone()) .client_state_height(client_height) .client_type(tm_client_type()) .latest_timestamp(timestamp) @@ -907,7 +906,7 @@ mod tests { .build(); { - let client_state = match ctx_a.client_state(&client_id_b).unwrap() { + let client_state = match ctx_a.client_state(&client_id).unwrap() { AnyClientState::Tendermint(tm_client_state) => tm_client_state, _ => panic!("never fails. not mock client"), }; @@ -924,10 +923,10 @@ mod tests { ctx_b.advance_host_chain_height_with_timestamp(future_timestamp); } - let client_state = ctx_a.client_state(&client_id_b).unwrap(); + let client_state = ctx_a.client_state(&client_id).unwrap(); assert!(client_state - .status(&ctx_a, &client_id_b) + .status(&ctx_a, &client_id) .unwrap() .is_expired()); } From 6b47dc7ada603e77b4b8d7cc0fb6bf1d2ad76d26 Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Tue, 17 Oct 2023 23:08:24 +0200 Subject: [PATCH 19/26] use mocks feature directly in dev-deps --- crates/ibc/Cargo.toml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crates/ibc/Cargo.toml b/crates/ibc/Cargo.toml index 231e43e1d..afbba5561 100644 --- a/crates/ibc/Cargo.toml +++ b/crates/ibc/Cargo.toml @@ -103,6 +103,4 @@ rstest = "0.18.1" tracing-subscriber = { version = "0.3.14", features = ["fmt", "env-filter", "json"]} test-log = { version = "0.2.10", features = ["trace"] } tendermint-rpc = { version = "0.34", features = ["http-client", "websocket-client"] } -tendermint-testgen = { version = "0.34" } # Needed for generating (synthetic) light blocks. -parking_lot = { version = "0.12.1" } -typed-builder = { version = "0.17.0" } +ibc = { path = ".", features = ["mocks"] } From f7cc80168c288aff6f608265a1f960d2f00961b9 Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Wed, 18 Oct 2023 16:29:22 +0200 Subject: [PATCH 20/26] include trusting_period and max_clock_drift in mock light client config --- crates/ibc/src/mock/context.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/crates/ibc/src/mock/context.rs b/crates/ibc/src/mock/context.rs index 742b9ccf2..d701b93dc 100644 --- a/crates/ibc/src/mock/context.rs +++ b/crates/ibc/src/mock/context.rs @@ -342,6 +342,11 @@ pub struct MockClientConfig { consensus_state_heights: Vec, #[builder(default = Timestamp::now())] latest_timestamp: Timestamp, + + #[builder(default = Duration::from_secs(64000))] + pub trusting_period: Duration, + #[builder(default = Duration::from_millis(3000))] + max_clock_drift: Duration, } /// Returns a MockContext with bare minimum initialization: no clients, no connections and no channels are @@ -723,6 +728,8 @@ impl MockContext { let client_state: TmClientState = TmClientStateConfig::builder() .chain_id(client.client_chain_id) .latest_height(client.client_state_height) + .trusting_period(client.trusting_period) + .max_clock_drift(client.max_clock_drift) .build() .try_into() .expect("never fails"); From 0d2d642bd1a0b0ea733d4acc98317aa5ef6e3009 Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Wed, 18 Oct 2023 16:31:51 +0200 Subject: [PATCH 21/26] revert advance chain height with timestamp --- crates/ibc/src/mock/context.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/crates/ibc/src/mock/context.rs b/crates/ibc/src/mock/context.rs index d701b93dc..25ddf438a 100644 --- a/crates/ibc/src/mock/context.rs +++ b/crates/ibc/src/mock/context.rs @@ -887,17 +887,15 @@ impl MockContext { /// Triggers the advancing of the host chain, by extending the history of blocks (or headers). pub fn advance_host_chain_height(&mut self) { - self.advance_host_chain_height_with_timestamp(self.host_timestamp().expect("Never fails")) - } - - /// Triggers the advancing of the host chain, by extending the history of blocks (or headers). - pub fn advance_host_chain_height_with_timestamp(&mut self, timestamp: Timestamp) { let latest_block = self.history.last().expect("history cannot be empty"); let new_block = HostBlock::generate_block( self.host_chain_id.clone(), self.host_chain_type, latest_block.height().increment().revision_height(), - timestamp, + latest_block + .timestamp() + .add(self.block_time) + .expect("Never fails"), ); // Append the new header at the tip of the history. From 3020a41c64350624c055e7e97d846371ef92616a Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Wed, 18 Oct 2023 16:28:49 +0200 Subject: [PATCH 22/26] update client expiry test --- .../ics02_client/handler/update_client.rs | 40 +++++-------------- 1 file changed, 10 insertions(+), 30 deletions(-) diff --git a/crates/ibc/src/core/ics02_client/handler/update_client.rs b/crates/ibc/src/core/ics02_client/handler/update_client.rs index 7b4bd990f..b84dc46de 100644 --- a/crates/ibc/src/core/ics02_client/handler/update_client.rs +++ b/crates/ibc/src/core/ics02_client/handler/update_client.rs @@ -121,7 +121,6 @@ where #[cfg(test)] mod tests { - use core::ops::Add; use core::str::FromStr; use core::time::Duration; @@ -145,7 +144,7 @@ mod tests { use crate::core::timestamp::Timestamp; use crate::mock::client_state::{client_type as mock_client_type, MockClientState}; use crate::mock::context::{ - AnyClientState, AnyConsensusState, MockClientConfig, MockContext, MockContextConfig, + AnyConsensusState, MockClientConfig, MockContext, MockContextConfig, }; use crate::mock::header::MockHeader; use crate::mock::host::{HostBlock, HostType}; @@ -883,7 +882,9 @@ mod tests { let timestamp = Timestamp::now(); - let mut ctx_a = MockContextConfig::builder() + let trusting_period = Duration::from_secs(64); + + let mut ctx = MockContextConfig::builder() .host_id(ChainId::new("mockgaiaA", 1).unwrap()) .latest_height(Height::new(1, 1).unwrap()) .latest_timestamp(timestamp) @@ -895,39 +896,18 @@ mod tests { .client_state_height(client_height) .client_type(tm_client_type()) .latest_timestamp(timestamp) + .trusting_period(trusting_period) .build(), ); - let mut ctx_b = MockContextConfig::builder() - .host_id(chain_id_b.clone()) - .host_type(HostType::SyntheticTendermint) - .latest_height(update_height) - .latest_timestamp(timestamp) - .build(); - + while ctx.host_timestamp().expect("no error") + < (timestamp + trusting_period).expect("no error") { - let client_state = match ctx_a.client_state(&client_id).unwrap() { - AnyClientState::Tendermint(tm_client_state) => tm_client_state, - _ => panic!("never fails. not mock client"), - }; - - let client_trusting_period = client_state.trusting_period; - - let future_timestamp = ctx_a - .host_timestamp() - .expect("never fails") - .add(client_trusting_period) - .expect("overflow"); - - ctx_a.advance_host_chain_height_with_timestamp(future_timestamp); - ctx_b.advance_host_chain_height_with_timestamp(future_timestamp); + ctx.advance_host_chain_height(); } - let client_state = ctx_a.client_state(&client_id).unwrap(); + let client_state = ctx.client_state(&client_id).unwrap(); - assert!(client_state - .status(&ctx_a, &client_id) - .unwrap() - .is_expired()); + assert!(client_state.status(&ctx, &client_id).unwrap().is_expired()); } } From 1d3bba81b988fcd1fad487107d72f5348023cd56 Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Wed, 18 Oct 2023 16:30:07 +0200 Subject: [PATCH 23/26] add test to check max_clock_drift --- .../ics02_client/handler/update_client.rs | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/crates/ibc/src/core/ics02_client/handler/update_client.rs b/crates/ibc/src/core/ics02_client/handler/update_client.rs index b84dc46de..14960bae2 100644 --- a/crates/ibc/src/core/ics02_client/handler/update_client.rs +++ b/crates/ibc/src/core/ics02_client/handler/update_client.rs @@ -910,4 +910,73 @@ mod tests { assert!(client_state.status(&ctx, &client_id).unwrap().is_expired()); } + + #[test] + fn test_client_update_max_clock_drift() { + let chain_id_b = ChainId::new("mockgaiaB", 1).unwrap(); + + let client_height = Height::new(1, 20).unwrap(); + + let client_id = ClientId::new(tm_client_type(), 0).unwrap(); + + let timestamp = Timestamp::now(); + + let max_clock_drift = Duration::from_secs(64); + + let ctx_a = MockContextConfig::builder() + .host_id(ChainId::new("mockgaiaA", 1).unwrap()) + .latest_height(Height::new(1, 1).unwrap()) + .latest_timestamp(timestamp) + .build() + .with_client_config( + MockClientConfig::builder() + .client_chain_id(chain_id_b.clone()) + .client_id(client_id.clone()) + .client_state_height(client_height) + .client_type(tm_client_type()) + .latest_timestamp(timestamp) + .max_clock_drift(max_clock_drift) + .build(), + ); + + let mut ctx_b = MockContextConfig::builder() + .host_id(chain_id_b.clone()) + .host_type(HostType::SyntheticTendermint) + .latest_height(client_height) + .latest_timestamp(timestamp) + .max_history_size(u64::MAX) + .build(); + + while ctx_b.host_timestamp().expect("no error") + < (ctx_a.host_timestamp().expect("no error") + max_clock_drift).expect("no error") + { + ctx_b.advance_host_chain_height(); + } + + // include current block + ctx_b.advance_host_chain_height(); + + let update_height = ctx_b.latest_height(); + + let signer = get_dummy_account_id(); + + let mut block = ctx_b.host_block(&update_height).unwrap().clone(); + block.set_trusted_height(client_height); + + let trusted_next_validator_set = match ctx_b.host_block(&client_height).expect("no error") { + HostBlock::SyntheticTendermint(header) => header.light_block.next_validators.clone(), + _ => panic!("unexpected host block type"), + }; + + block.set_trusted_next_validators_set(trusted_next_validator_set); + + let msg = MsgUpdateClient { + client_id, + client_message: block.clone().into(), + signer, + }; + + let res = validate(&ctx_a, MsgUpdateOrMisbehaviour::UpdateClient(msg.clone())); + assert!(res.is_err()); + } } From 554ac480352d9be9eb41952ca2d172a4847f14ed Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Wed, 18 Oct 2023 16:46:14 +0200 Subject: [PATCH 24/26] rm TODO comments in favor of gh issue --- crates/ibc/src/core/ics02_client/handler/update_client.rs | 8 ++------ crates/ibc/src/mock/context.rs | 4 +--- crates/ibc/src/mock/host.rs | 3 --- 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/crates/ibc/src/core/ics02_client/handler/update_client.rs b/crates/ibc/src/core/ics02_client/handler/update_client.rs index 14960bae2..40f853f5f 100644 --- a/crates/ibc/src/core/ics02_client/handler/update_client.rs +++ b/crates/ibc/src/core/ics02_client/handler/update_client.rs @@ -272,9 +272,7 @@ mod tests { ); let ctx_b_val_history = vec![ - // TODO(rano): the validator set params during setups. - // Here I picked the default validator set which is - // used at host side client creation. + // First two validator sets are default at client creation // // validator set of height-20 vec![ @@ -366,9 +364,7 @@ mod tests { ); let ctx_b_val_history = vec![ - // TODO(rano): the validator set params during setups. - // Here I picked the default validator set which is - // used at host side client creation. + // First two validator sets are default at client creation // // validator set of height-20 vec![ diff --git a/crates/ibc/src/mock/context.rs b/crates/ibc/src/mock/context.rs index 25ddf438a..53b64956b 100644 --- a/crates/ibc/src/mock/context.rs +++ b/crates/ibc/src/mock/context.rs @@ -230,8 +230,7 @@ pub struct MockContextConfig { #[builder(default = Duration::from_secs(DEFAULT_BLOCK_TIME_SECS))] block_time: Duration, - // TODO(rano): make max_history_size optional - // should be default to `validator_set_history.unwrap_or(6) - 1` + // may panic if validator_set_history size is less than max_history_size + 1 #[builder(default = 5)] max_history_size: u64, @@ -724,7 +723,6 @@ impl MockContext { }) .collect(); - // TODO(rano): parametrize the other params let client_state: TmClientState = TmClientStateConfig::builder() .chain_id(client.client_chain_id) .latest_height(client.client_state_height) diff --git a/crates/ibc/src/mock/host.rs b/crates/ibc/src/mock/host.rs index 4f7436cf9..30444b478 100644 --- a/crates/ibc/src/mock/host.rs +++ b/crates/ibc/src/mock/host.rs @@ -157,8 +157,6 @@ impl HostBlock { height: u64, timestamp: Timestamp, ) -> SyntheticTmBlock { - // TODO(rano): use HeaderBuilder pattern - let validators = [ TestgenValidator::new("1").voting_power(50), TestgenValidator::new("2").voting_power(50), @@ -175,7 +173,6 @@ impl HostBlock { .expect("Never fails"); SyntheticTmBlock { - // TODO(rano): don't use constant for rev_height trusted_height: Height::new(chain_id.revision_number(), 1).expect("Never fails"), trusted_next_validators: light_block.next_validators.clone(), light_block, From 0da962b1a9c90b97f839ccaba28dcbc517b0e91d Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Wed, 18 Oct 2023 16:55:58 +0200 Subject: [PATCH 25/26] revert ctx_a renaming --- .../ics02_client/handler/update_client.rs | 30 ++++++++----------- 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/crates/ibc/src/core/ics02_client/handler/update_client.rs b/crates/ibc/src/core/ics02_client/handler/update_client.rs index 40f853f5f..ddd7bef73 100644 --- a/crates/ibc/src/core/ics02_client/handler/update_client.rs +++ b/crates/ibc/src/core/ics02_client/handler/update_client.rs @@ -205,7 +205,7 @@ mod tests { let update_height = Height::new(1, 21).unwrap(); let chain_id_b = ChainId::new("mockgaiaB", 1).unwrap(); - let mut ctx_a = MockContext::new( + let mut ctx = MockContext::new( ChainId::new("mockgaiaA", 1).unwrap(), HostType::Mock, 5, @@ -233,18 +233,15 @@ mod tests { signer, }; - let res = validate(&ctx_a, MsgUpdateOrMisbehaviour::UpdateClient(msg.clone())); + let res = validate(&ctx, MsgUpdateOrMisbehaviour::UpdateClient(msg.clone())); assert!(res.is_ok()); - let res = execute( - &mut ctx_a, - MsgUpdateOrMisbehaviour::UpdateClient(msg.clone()), - ); + let res = execute(&mut ctx, MsgUpdateOrMisbehaviour::UpdateClient(msg.clone())); assert!(res.is_ok(), "result: {res:?}"); - let client_state = ctx_a.client_state(&msg.client_id).unwrap(); + let client_state = ctx.client_state(&msg.client_id).unwrap(); assert!(client_state - .status(&ctx_a, &msg.client_id) + .status(&ctx, &msg.client_id) .unwrap() .is_active()); assert_eq!(client_state.latest_height(), latest_header_height); @@ -428,7 +425,7 @@ mod tests { let update_height = Height::new(1, 21).unwrap(); let chain_id_b = ChainId::new("mockgaiaB", 1).unwrap(); - let mut ctx_a = MockContext::new( + let mut ctx = MockContext::new( ChainId::new("mockgaiaA", 1).unwrap(), HostType::Mock, 5, @@ -457,18 +454,15 @@ mod tests { signer, }; - let res = validate(&ctx_a, MsgUpdateOrMisbehaviour::UpdateClient(msg.clone())); + let res = validate(&ctx, MsgUpdateOrMisbehaviour::UpdateClient(msg.clone())); assert!(res.is_ok()); - let res = execute( - &mut ctx_a, - MsgUpdateOrMisbehaviour::UpdateClient(msg.clone()), - ); + let res = execute(&mut ctx, MsgUpdateOrMisbehaviour::UpdateClient(msg.clone())); assert!(res.is_ok(), "result: {res:?}"); - let client_state = ctx_a.client_state(&msg.client_id).unwrap(); + let client_state = ctx.client_state(&msg.client_id).unwrap(); assert!(client_state - .status(&ctx_a, &msg.client_id) + .status(&ctx, &msg.client_id) .unwrap() .is_active()); assert_eq!(client_state.latest_height(), latest_header_height); @@ -608,7 +602,7 @@ mod tests { let chain_start_height = Height::new(1, 11).unwrap(); - let ctx_a = MockContext::new( + let ctx = MockContext::new( ChainId::new("mockgaiaA", 1).unwrap(), HostType::Mock, 5, @@ -638,7 +632,7 @@ mod tests { signer, }; - let res = validate(&ctx_a, MsgUpdateOrMisbehaviour::UpdateClient(msg)); + let res = validate(&ctx, MsgUpdateOrMisbehaviour::UpdateClient(msg)); assert!(res.is_err()); } From 57180f9e355b0824bd9682c5dd3b3ad98b2450bf Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Wed, 18 Oct 2023 17:01:16 +0200 Subject: [PATCH 26/26] add changelog entry --- .../unreleased/improvements/538-test-for-client-expiry.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .changelog/unreleased/improvements/538-test-for-client-expiry.md diff --git a/.changelog/unreleased/improvements/538-test-for-client-expiry.md b/.changelog/unreleased/improvements/538-test-for-client-expiry.md new file mode 100644 index 000000000..701905ada --- /dev/null +++ b/.changelog/unreleased/improvements/538-test-for-client-expiry.md @@ -0,0 +1,2 @@ +- Add test for expired client status. + ([\#538](https://github.com/cosmos/ibc-rs/issues/538))