Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

imp(testkit): Mock IBC context with basecoin-store types #1068

Merged
merged 24 commits into from
Feb 7, 2024
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,6 @@ tendermint-testgen = { version = "0.34.0", default-features = fals
# parity dependencies
parity-scale-codec = { version = "3.6.5", default-features = false, features = ["full"] }
scale-info = { version = "2.10.0", default-features = false, features = ["derive"] }

[patch.crates-io]
Farhad-Shabani marked this conversation as resolved.
Show resolved Hide resolved
ibc-proto = { path = "../ibc-proto-rs" }
8 changes: 7 additions & 1 deletion ibc-core/ics23-commitment/types/src/commitment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,11 +144,17 @@ impl<'a> TryFrom<&'a CommitmentProofBytes> for MerkleProof {
)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(Clone, PartialEq, Eq, Hash, Default)]
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct CommitmentPrefix {
bytes: Vec<u8>,
}

impl Default for CommitmentPrefix {
Farhad-Shabani marked this conversation as resolved.
Show resolved Hide resolved
fn default() -> Self {
Self { bytes: vec![0x00] }
}
}

impl CommitmentPrefix {
pub fn as_bytes(&self) -> &[u8] {
&self.bytes
Expand Down
3 changes: 3 additions & 0 deletions ibc-testkit/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,13 @@ typed-builder = { version = "0.18.0" }
# ibc dependencies
ibc = { workspace = true, features = ["std"] }
ibc-proto = { workspace = true }
ibc-query = { version = "0.50.0", path = "../ibc-query" }
basecoin-store = { package = "basecoin-store", path = "../../basecoin-rs/crates/store" }

# cosmos dependencies
tendermint = { workspace = true }
tendermint-testgen = { workspace = true }
tendermint-proto = { workspace = true }

[dev-dependencies]
env_logger = "0.11.0"
Expand Down
2 changes: 1 addition & 1 deletion ibc-testkit/src/fixtures/core/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ mod tests {
"07-tendermint",
"0-5",
"0-5,0-7",
"0a102f6962632e6d6f636b2e48656164657212040a021005",
"0a102f6962632e6d6f636b2e48656164657212060a0210051200",
];

let tests: Vec<Test> = vec![
Expand Down
17 changes: 10 additions & 7 deletions ibc-testkit/src/fixtures/core/context.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
use alloc::sync::Arc;
use alloc::fmt::Debug;
use core::cmp::min;
use core::ops::{Add, Sub};
use core::time::Duration;

use basecoin_store::context::ProvableStore;
use ibc::core::client::types::Height;
use ibc::core::host::types::identifiers::ChainId;
use ibc::core::primitives::prelude::*;
use ibc::core::primitives::Timestamp;
use parking_lot::Mutex;
use tendermint_testgen::Validator as TestgenValidator;
use typed_builder::TypedBuilder;

use crate::hosts::block::{HostBlock, HostType};
use crate::testapp::ibc::core::types::{MockContext, MockIbcStore, DEFAULT_BLOCK_TIME_SECS};
use crate::testapp::ibc::core::types::{MockGenericContext, MockIbcStore, DEFAULT_BLOCK_TIME_SECS};

/// Configuration of the `MockContext` type for generating dummy contexts.
#[derive(Debug, TypedBuilder)]
#[builder(build_method(into = MockContext))]
#[builder(build_method(into))]
pub struct MockContextConfig {
#[builder(default = HostType::Mock)]
host_type: HostType,
Expand All @@ -41,7 +41,10 @@ pub struct MockContextConfig {
latest_timestamp: Timestamp,
}

impl From<MockContextConfig> for MockContext {
impl<S> From<MockContextConfig> for MockGenericContext<S>
where
S: ProvableStore + Debug + Default,
{
fn from(params: MockContextConfig) -> Self {
assert_ne!(
params.max_history_size, 0,
Expand Down Expand Up @@ -115,13 +118,13 @@ impl From<MockContextConfig> for MockContext {
.collect()
};

MockContext {
MockGenericContext {
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())),
ibc_store: MockIbcStore::default(),
}
}
}
2 changes: 1 addition & 1 deletion ibc-testkit/src/fixtures/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ pub enum Expect {
Failure(Option<ContextError>),
}

#[derive(Clone, Debug)]
#[derive(Debug)]
pub struct Fixture<M: Debug> {
pub ctx: MockContext,
pub msg: M,
Expand Down
59 changes: 36 additions & 23 deletions ibc-testkit/src/relayer/context.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
use alloc::fmt::Debug;

use basecoin_store::context::ProvableStore;
use ibc::core::client::types::Height;
use ibc::core::handler::types::error::ContextError;
use ibc::core::host::types::identifiers::ClientId;
Expand All @@ -6,7 +9,7 @@ use ibc::core::primitives::prelude::*;
use ibc::core::primitives::Signer;

use crate::testapp::ibc::clients::AnyClientState;
use crate::testapp::ibc::core::types::MockContext;
use crate::testapp::ibc::core::types::MockGenericContext;
/// Trait capturing all dependencies (i.e., the context) which algorithms in ICS18 require to
/// relay packets between chains. This trait comprises the dependencies towards a single chain.
/// Most of the functions in this represent wrappers over the ABCI interface.
Expand All @@ -24,7 +27,10 @@ pub trait RelayerContext {
fn signer(&self) -> Signer;
}

impl RelayerContext for MockContext {
impl<S> RelayerContext for MockGenericContext<S>
where
S: ProvableStore + Debug,
{
fn query_latest_height(&self) -> Result<Height, ContextError> {
ValidationContext::host_height(self)
}
Expand Down Expand Up @@ -59,7 +65,7 @@ mod tests {
use crate::relayer::error::RelayerError;
use crate::testapp::ibc::clients::mock::client_state::client_type as mock_client_type;
use crate::testapp::ibc::core::router::MockRouter;
use crate::testapp::ibc::core::types::MockClientConfig;
use crate::testapp::ibc::core::types::{MockClientConfig, MockContext};

/// Builds a `ClientMsg::UpdateClient` for a client with id `client_id` running on the `dest`
/// context, assuming that the latest header on the source context is `src_header`.
Expand Down Expand Up @@ -126,30 +132,37 @@ mod tests {
let mut ctx_a = MockContextConfig::builder()
.host_id(chain_id_a.clone())
.latest_height(chain_a_start_height)
.build()
.with_client_config(
MockClientConfig::builder()
.client_chain_id(chain_id_b.clone())
.client_id(client_on_a_for_b.clone())
.latest_height(client_on_a_for_b_height)
.client_type(tm_client_type()) // The target host chain (B) is synthetic TM.
.build(),
);
// dummy; not actually used in client updates
let mut router_a = MockRouter::new_with_transfer();
.build::<MockContext>();

let mut ctx_b = MockContextConfig::builder()
.host_id(chain_id_b)
.host_id(chain_id_b.clone())
.host_type(HostType::SyntheticTendermint)
.latest_height(chain_b_start_height)
.build()
.with_client_config(
MockClientConfig::builder()
.client_chain_id(chain_id_a)
.client_id(client_on_b_for_a.clone())
.latest_height(client_on_b_for_a_height)
.build(),
);
.latest_timestamp(ctx_a.timestamp_at(chain_a_start_height.decrement().unwrap())) // chain B is running slower than chain A
.build::<MockContext>();

ctx_a = ctx_a.with_client_config(
MockClientConfig::builder()
.client_chain_id(chain_id_b)
.client_id(client_on_a_for_b.clone())
.latest_height(client_on_a_for_b_height)
.latest_timestamp(ctx_b.timestamp_at(client_on_a_for_b_height))
.client_type(tm_client_type()) // The target host chain (B) is synthetic TM.
.build(),
);

ctx_b = ctx_b.with_client_config(
MockClientConfig::builder()
.client_chain_id(chain_id_a)
.client_id(client_on_b_for_a.clone())
.latest_height(client_on_b_for_a_height)
.latest_timestamp(ctx_a.timestamp_at(client_on_b_for_a_height))
.build(),
);

// dummy; not actually used in client updates
let mut router_a = MockRouter::new_with_transfer();

// dummy; not actually used in client updates
let mut router_b = MockRouter::new_with_transfer();

Expand Down
39 changes: 26 additions & 13 deletions ibc-testkit/src/testapp/ibc/clients/mock/client_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,8 @@ use crate::testapp::ibc::clients::mock::client_state::client_type as mock_client
use crate::testapp::ibc::clients::mock::consensus_state::MockConsensusState;
use crate::testapp::ibc::clients::mock::header::MockHeader;
use crate::testapp::ibc::clients::mock::misbehaviour::Misbehaviour;
use crate::testapp::ibc::clients::mock::proto::{
ClientState as RawMockClientState, Header as RawMockHeader,
};
use crate::testapp::ibc::clients::mock::proto::ClientState as RawMockClientState;
use crate::testapp::ibc::utils::{duration_gpb_to_ibc, duration_ibc_to_gbp};

pub const MOCK_CLIENT_STATE_TYPE_URL: &str = "/ibc.mock.ClientState";
pub const MOCK_CLIENT_TYPE: &str = "9999-mock";
Expand All @@ -39,14 +38,18 @@ pub fn client_type() -> ClientType {
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct MockClientState {
pub header: MockHeader,
pub frozen_height: Option<Height>,
pub max_clock_drift: Option<Duration>,
pub trusing_period: Option<Duration>,
pub frozen: bool,
}

impl MockClientState {
pub fn new(header: MockHeader) -> Self {
Self {
header,
frozen_height: None,
max_clock_drift: None,
trusing_period: None,
frozen: false,
}
}

Expand All @@ -58,15 +61,15 @@ impl MockClientState {
None
}

pub fn with_frozen_height(self, frozen_height: Height) -> Self {
pub fn with_frozen_height(self, _frozen_height: Height) -> Self {
Self {
frozen_height: Some(frozen_height),
frozen: true,
..self
}
}

pub fn is_frozen(&self) -> bool {
self.frozen_height.is_some()
self.frozen
}

fn expired(&self, _elapsed: Duration) -> bool {
Expand All @@ -80,17 +83,27 @@ impl TryFrom<RawMockClientState> for MockClientState {
type Error = ClientError;

fn try_from(raw: RawMockClientState) -> Result<Self, Self::Error> {
Ok(Self::new(raw.header.expect("Never fails").try_into()?))
Ok(Self {
header: raw
.header
.ok_or(ClientError::Other {
description: "header is not present".into(),
})?
.try_into()?,
max_clock_drift: raw.max_clock_drift.map(duration_gpb_to_ibc),
trusing_period: raw.trusing_period.map(duration_gpb_to_ibc),
frozen: raw.frozen,
})
}
}

impl From<MockClientState> for RawMockClientState {
fn from(value: MockClientState) -> Self {
RawMockClientState {
header: Some(RawMockHeader {
height: Some(value.header.height().into()),
timestamp: value.header.timestamp.nanoseconds(),
}),
header: Some(value.header.into()),
max_clock_drift: value.max_clock_drift.map(duration_ibc_to_gbp),
trusing_period: value.trusing_period.map(duration_ibc_to_gbp),
frozen: value.frozen,
}
}
}
Expand Down
12 changes: 4 additions & 8 deletions ibc-testkit/src/testapp/ibc/clients/mock/consensus_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ use ibc::core::primitives::Timestamp;
use ibc::primitives::proto::{Any, Protobuf};

use crate::testapp::ibc::clients::mock::header::MockHeader;
use crate::testapp::ibc::clients::mock::proto::{
ConsensusState as RawMockConsensusState, Header as RawMockHeader,
};
use crate::testapp::ibc::clients::mock::proto::ConsensusState as RawMockConsensusState;
pub const MOCK_CONSENSUS_STATE_TYPE_URL: &str = "/ibc.mock.ConsensusState";

#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
Expand Down Expand Up @@ -40,7 +38,7 @@ impl TryFrom<RawMockConsensusState> for MockConsensusState {
let raw_header = raw.header.ok_or(ClientError::MissingRawConsensusState)?;

Ok(Self {
header: MockHeader::try_from(raw_header)?,
header: raw_header.try_into()?,
root: CommitmentRoot::from(vec![0]),
})
}
Expand All @@ -49,10 +47,8 @@ impl TryFrom<RawMockConsensusState> for MockConsensusState {
impl From<MockConsensusState> for RawMockConsensusState {
fn from(value: MockConsensusState) -> Self {
RawMockConsensusState {
header: Some(RawMockHeader {
height: Some(value.header.height().into()),
timestamp: value.header.timestamp.nanoseconds(),
}),
header: Some(value.header.into()),
bytes: value.root.into_vec(),
}
}
}
Expand Down
20 changes: 13 additions & 7 deletions ibc-testkit/src/testapp/ibc/clients/mock/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use ibc::core::primitives::Timestamp;
use ibc::primitives::proto::{Any, Protobuf};

use crate::testapp::ibc::clients::mock::proto::Header as RawMockHeader;
use crate::testapp::ibc::utils::{timestamp_gpb_to_ibc, timestamp_ibc_to_gpb};

pub const MOCK_HEADER_TYPE_URL: &str = "/ibc.mock.Header";

Expand Down Expand Up @@ -45,11 +46,16 @@ impl TryFrom<RawMockHeader> for MockHeader {
Ok(MockHeader {
height: raw
.height
.and_then(|raw_height| raw_height.try_into().ok())
.ok_or(ClientError::MissingClientMessage)?,

timestamp: Timestamp::from_nanoseconds(raw.timestamp)
.map_err(ClientError::InvalidPacketTimestamp)?,
.ok_or(ClientError::Other {
description: "missing height".into(),
})?
.try_into()?,
timestamp: raw
.timestamp
.map(timestamp_gpb_to_ibc)
.ok_or(ClientError::Other {
description: "missing timestamp".into(),
})?,
})
}
}
Expand All @@ -58,7 +64,7 @@ impl From<MockHeader> for RawMockHeader {
fn from(value: MockHeader) -> Self {
RawMockHeader {
height: Some(value.height.into()),
timestamp: value.timestamp.nanoseconds(),
timestamp: Some(timestamp_ibc_to_gpb(value.timestamp)),
}
}
}
Expand Down Expand Up @@ -130,7 +136,7 @@ mod tests {
&bytes,
&[
10, 16, 47, 105, 98, 99, 46, 109, 111, 99, 107, 46, 72, 101, 97, 100, 101, 114, 18,
6, 10, 4, 8, 1, 16, 10
8, 10, 4, 8, 1, 16, 10, 18, 0
]
);
}
Expand Down
9 changes: 6 additions & 3 deletions ibc-testkit/src/testapp/ibc/clients/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
pub mod mock;

use alloc::fmt::Debug;

use basecoin_store::context::ProvableStore;
use derive_more::{From, TryInto};
use ibc::clients::tendermint::client_state::ClientState as TmClientState;
use ibc::clients::tendermint::consensus_state::ConsensusState as TmConsensusState;
Expand All @@ -17,11 +20,11 @@ use crate::testapp::ibc::clients::mock::client_state::{
use crate::testapp::ibc::clients::mock::consensus_state::{
MockConsensusState, MOCK_CONSENSUS_STATE_TYPE_URL,
};
use crate::testapp::ibc::core::types::MockContext;
use crate::testapp::ibc::core::types::MockGenericContext;

#[derive(Debug, Clone, From, PartialEq, ClientState)]
#[validation(MockContext)]
#[execution(MockContext)]
#[validation(MockGenericContext<S: ProvableStore + Debug>)]
#[execution(MockGenericContext<S: ProvableStore + Debug>)]
pub enum AnyClientState {
Tendermint(TmClientState),
Mock(MockClientState),
Expand Down
Loading
Loading