pub mod mock;
pub mod tendermint;
use core::fmt::Debug;
use core::ops::Add;
use core::time::Duration;
use ibc::core::client::context::consensus_state::ConsensusState;
use ibc::core::client::types::Height;
use ibc::core::primitives::prelude::*;
use ibc::core::primitives::Timestamp;
use ibc::primitives::proto::Any;
pub use self::mock::MockHost;
pub use self::tendermint::TendermintHost;
use crate::testapp::ibc::clients::{AnyClientState, AnyConsensusState};
pub type HostClientState<H> = <H as TestHost>::ClientState;
pub type HostBlock<H> = <H as TestHost>::Block;
pub type HostBlockParams<H> = <H as TestHost>::BlockParams;
pub type HostLightClientParams<H> = <H as TestHost>::LightClientParams;
pub type HostHeader<H> = <HostBlock<H> as TestBlock>::Header;
pub type HostConsensusState<H> = <HostHeader<H> as TestHeader>::ConsensusState;
pub trait TestHost: Default + Debug + Sized {
type Block: TestBlock;
type ClientState: Into<AnyClientState> + Debug;
type BlockParams: Debug + Default;
type LightClientParams: Debug + Default;
fn history(&self) -> &Vec<Self::Block>;
fn is_empty(&self) -> bool {
self.history().is_empty()
}
fn latest_height(&self) -> Height {
self.latest_block().height()
}
fn latest_block(&self) -> Self::Block {
self.history().last().cloned().expect("no error")
}
fn get_block(&self, target_height: &Height) -> Option<Self::Block> {
self.history()
.get(target_height.revision_height() as usize - 1)
.cloned() }
fn push_block(&mut self, block: Self::Block);
fn commit_block(
&mut self,
commitment_root: Vec<u8>,
block_time: Duration,
params: &Self::BlockParams,
) {
let latest_block = self.latest_block();
let height = TestBlock::height(&latest_block)
.increment()
.revision_height();
let timestamp = TestBlock::timestamp(&latest_block)
.add(block_time)
.expect("Never fails");
let new_block = self.generate_block(commitment_root, height, timestamp, params);
self.push_block(new_block);
}
fn generate_block(
&self,
commitment_root: Vec<u8>,
height: u64,
timestamp: Timestamp,
params: &Self::BlockParams,
) -> Self::Block;
fn generate_client_state(
&self,
latest_height: &Height,
params: &Self::LightClientParams,
) -> Self::ClientState;
fn validate(&self) -> Result<(), String> {
let latest_height = self.latest_height();
let mut current_height = Height::min(latest_height.revision_number());
while current_height <= latest_height {
if current_height != self.get_block(¤t_height).expect("no error").height() {
return Err("block height does not match".to_owned());
}
current_height = current_height.increment();
}
Ok(())
}
}
pub trait TestBlock: Clone + Debug {
type Header: TestHeader;
fn height(&self) -> Height;
fn timestamp(&self) -> Timestamp;
fn into_header_with_trusted(self, trusted_block: &Self) -> Self::Header;
fn into_header(self) -> Self::Header {
self.clone().into_header_with_trusted(&self)
}
}
pub trait TestHeader: Clone + Debug + Into<Any> {
type ConsensusState: ConsensusState + Into<AnyConsensusState> + From<Self> + Clone + Debug;
fn height(&self) -> Height;
fn timestamp(&self) -> Timestamp;
fn into_consensus_state(self) -> Self::ConsensusState {
Self::ConsensusState::from(self)
}
}