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

Use custom options of the create client command #2004

Merged
merged 29 commits into from
Apr 4, 2022
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
3883068
Rework of CreateParams -> ClientOptions
mzabaluev Mar 22, 2022
db563e4
Split CreateOptions and ClientSettings
mzabaluev Mar 23, 2022
abbd4dc
Update docs in relayer/src/chain/client.rs
mzabaluev Mar 23, 2022
25665be
Improve help for --clock-drift
mzabaluev Mar 23, 2022
22a77c1
Merge branch 'mikhail/create-client-options' of github.com:informalsy…
mzabaluev Mar 23, 2022
b661a55
Rework ClientSettings
mzabaluev Mar 25, 2022
2acb458
Merge branch 'master' into mikhail/create-client-options
mzabaluev Mar 28, 2022
08748ee
Builder pattern for foreign client tests
mzabaluev Mar 29, 2022
f18a9c1
Add client setting overrides to the test framework
mzabaluev Mar 29, 2022
e4ba706
Draft test for custom client settings
mzabaluev Mar 29, 2022
db8f60f
Fix clippy lints
mzabaluev Mar 29, 2022
5745837
Merge branch 'master' into mikhail/create-client-options
mzabaluev Mar 29, 2022
df321e6
Post-merge fixes
mzabaluev Mar 29, 2022
a75d880
client_settings test: query state of the client
mzabaluev Mar 29, 2022
f8f7d92
Make client_settings test work
mzabaluev Mar 29, 2022
fe2fe9f
Merge branch 'master' into mikhail/create-client-options
mzabaluev Mar 30, 2022
9d4b8cf
Clean up client_settings test
mzabaluev Mar 30, 2022
658ee0d
Add a test for default client settings
mzabaluev Mar 30, 2022
a2d6688
Use the IBC TrustThreshold type in client settings
mzabaluev Mar 30, 2022
29e891c
Merge branch 'master' into mikhail/create-client-options
mzabaluev Mar 30, 2022
67ffff4
Warn when client clock drift exceeds max_block_time
mzabaluev Mar 30, 2022
7e45352
Changelog entry for #2004
mzabaluev Mar 30, 2022
4c76c3a
Simplify overrides for ClientSettingsTest
mzabaluev Mar 31, 2022
f068c16
integration-test: Remove an unused structure
mzabaluev Mar 31, 2022
9df0cba
relayer: Sanitize imports in mod chain
mzabaluev Mar 31, 2022
009d1dd
Split client command options from client settings
mzabaluev Apr 1, 2022
d4ed916
Rename ClientSettings::Cosmos -> Tendermint
mzabaluev Apr 1, 2022
75d60a7
Fix clippy lint
mzabaluev Apr 1, 2022
5c3bef4
Merge branch 'master' into mikhail/create-client-options
mzabaluev Apr 1, 2022
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
16 changes: 10 additions & 6 deletions relayer-cli/src/commands/tx/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ use ibc::core::ics02_client::client_state::ClientState;
use ibc::core::ics24_host::identifier::{ChainId, ClientId};
use ibc::events::IbcEvent;
use ibc_proto::ibc::core::client::v1::QueryClientStatesRequest;
use ibc_relayer::chain::client::ClientSettings;
use ibc_relayer::chain::cosmos;
use ibc_relayer::chain::handle::ChainHandle;
use ibc_relayer::config::Config;
use ibc_relayer::foreign_client::{CreateParams, ForeignClient};
use ibc_relayer::foreign_client::ForeignClient;
use tendermint_light_client_verifier::types::TrustThreshold;

use crate::application::app_config;
Expand All @@ -25,13 +27,15 @@ pub struct TxCreateClientCmd {
#[clap(required = true, help = "identifier of the source chain")]
src_chain_id: ChainId,

/// Override the default clock drift specified in the configuration.
/// The maximum allowed clock drift for this client.
///
/// The clock drift is a correction parameter. It helps deal with clocks
/// that are only approximately synchronized between the source and destination chains
/// of this client.
/// The destination chain for this client uses the clock drift parameter when deciding
/// to accept or reject a new header (originating from the source chain) for this client.
/// If this option is not specified, a suitable clock drift value is derived from the chain
/// configurations.
#[clap(short = 'd', long)]
clock_drift: Option<humantime::Duration>,

Expand Down Expand Up @@ -67,15 +71,15 @@ impl Runnable for TxCreateClientCmd {

let client = ForeignClient::restore(ClientId::default(), chains.dst, chains.src);

let params = CreateParams {
clock_drift: self.clock_drift.map(Into::into),
let settings = ClientSettings::Cosmos(cosmos::client::Settings {
max_clock_drift: self.clock_drift.map(Into::into),
trusting_period: self.trusting_period.map(Into::into),
trust_threshold: self.trust_threshold,
};
});

// Trigger client creation via the "build" interface, so that we obtain the resulting event
let res: Result<IbcEvent, Error> = client
.build_create_client_and_send(&params)
.build_create_client_and_send(settings)
.map_err(Error::foreign_client);

match res {
Expand Down
6 changes: 4 additions & 2 deletions relayer/src/chain.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use alloc::sync::Arc;
use core::convert::TryFrom;

use tendermint::block::Height;
use tokio::runtime::Runtime as TokioRuntime;

pub use cosmos::CosmosSdkChain;
Expand Down Expand Up @@ -36,6 +35,7 @@ use ibc_proto::ibc::core::commitment::v1::MerkleProof;
use ibc_proto::ibc::core::connection::v1::{
QueryClientConnectionsRequest, QueryConnectionsRequest,
};
use tendermint::block::Height;
use tendermint_rpc::endpoint::broadcast::tx_sync::Response as TxResponse;

use crate::connection::ConnectionMsgType;
Expand All @@ -45,8 +45,10 @@ use crate::keyring::{KeyEntry, KeyRing};
use crate::light_client::LightClient;
use crate::{config::ChainConfig, event::monitor::EventReceiver};

use self::client::ClientSettings;
use self::tx::TrackedMsgs;

pub mod client;
pub mod cosmos;
pub mod counterparty;
pub mod handle;
Expand Down Expand Up @@ -309,7 +311,7 @@ pub trait ChainEndpoint: Sized {
fn build_client_state(
&self,
height: ICSHeight,
dst_config: ChainConfig,
settings: ClientSettings,
) -> Result<Self::ClientState, Error>;

fn build_consensus_state(
Expand Down
28 changes: 28 additions & 0 deletions relayer/src/chain/client.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//! Data structures and logic to set up IBC client's parameters.

use crate::chain::cosmos;
use crate::config::ChainConfig;

/// Client parameters for the `build_create_client` operation.
///
/// The parameters are specialized for each supported chain type.
#[derive(Clone, Debug)]
pub enum ClientSettings {
Cosmos(cosmos::client::Settings),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Neat!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if Cosmos or Tendermint is the right name to use here.
AnyClientState uses Tendermint, maybe we should use it here too for consistency?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a very good point. Tendermint is more appropriate than Cosmos.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OTOH the module hierarchy under chain uses cosmos. This is a relayer API anyway, so we don't have to be super-diligent.

}

impl ClientSettings {
/// Fills in some settings if they have not been specified,
/// using the configuration of the source and the destination chain.
pub fn fill_in_from_chain_configs(
&mut self,
src_chain_config: &ChainConfig,
dst_chain_config: &ChainConfig,
) {
use ClientSettings::*;

match self {
Cosmos(config) => config.fill_in_from_chain_configs(src_chain_config, dst_chain_config),
}
}
}
44 changes: 21 additions & 23 deletions relayer/src/chain/cosmos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ use ibc_proto::ibc::core::connection::v1::{
QueryClientConnectionsRequest, QueryConnectionsRequest,
};

use crate::chain::{cosmos::account::query_account, QueryResponse, StatusResponse};
use crate::config::types::Memo;
use crate::config::{AddressType, ChainConfig, GasPrice};
use crate::error::Error;
Expand All @@ -95,11 +94,13 @@ use ibc::core::ics24_host::path::{
ConnectionsPath, ReceiptsPath, SeqRecvsPath,
};

use self::account::{Account, AccountNumber, AccountSequence};

use super::{tx::TrackedMsgs, ChainEndpoint, HealthCheck};
use self::account::{query_account, Account, AccountNumber, AccountSequence};
use super::client::ClientSettings;
use super::tx::TrackedMsgs;
use super::{ChainEndpoint, HealthCheck, QueryResponse, StatusResponse};

pub mod account;
pub mod client;
pub mod compatibility;
pub mod version;

Expand Down Expand Up @@ -2077,17 +2078,28 @@ impl ChainEndpoint for CosmosSdkChain {
fn build_client_state(
&self,
height: ICSHeight,
dst_config: ChainConfig,
settings: ClientSettings,
) -> Result<Self::ClientState, Error> {
let settings = match settings {
ClientSettings::Cosmos(s) => s,
};
let max_clock_drift = settings
.max_clock_drift
.expect("`fill_in_from_chain_configs` should have been called");
let unbonding_period = self.unbonding_period()?;

let max_clock_drift = calculate_client_state_drift(self.config(), &dst_config);
let trusting_period = settings
.trusting_period
.unwrap_or_else(|| self.trusting_period(unbonding_period));
let trust_threshold = settings
.trust_threshold
.unwrap_or(self.config.trust_threshold)
.into();

// Build the client state.
ClientState::new(
self.id().clone(),
self.config.trust_threshold.into(),
self.trusting_period(unbonding_period),
trust_threshold,
trusting_period,
unbonding_period,
max_clock_drift,
height,
Expand Down Expand Up @@ -2550,20 +2562,6 @@ fn mul_ceil(a: u64, f: f64) -> BigInt {
(f * a).ceil().to_integer()
}

/// Compute the `max_clock_drift` for a (new) client state
/// as a function of the configuration of the source chain
/// and the destination chain configuration.
///
/// The client state clock drift must account for destination
/// chain block frequency and clock drift on source and dest.
/// https://github.com/informalsystems/ibc-rs/issues/1445
fn calculate_client_state_drift(
src_chain_config: &ChainConfig,
dst_chain_config: &ChainConfig,
) -> Duration {
src_chain_config.clock_drift + dst_chain_config.clock_drift + dst_chain_config.max_block_time
}

#[cfg(test)]
mod tests {
use ibc::{
Expand Down
41 changes: 41 additions & 0 deletions relayer/src/chain/cosmos/client.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//! Cosmos-specific client settings.

use core::time::Duration;

use tendermint_light_client_verifier::types::TrustThreshold;

use crate::config::ChainConfig;

/// Cosmos-specific client parameters for the `build_create_client` operation.
/// If set, the options override the defaults taken from the source chain configuration.
#[derive(Clone, Debug, Default)]
pub struct Settings {
pub max_clock_drift: Option<Duration>,
pub trusting_period: Option<Duration>,
pub trust_threshold: Option<TrustThreshold>,
}

impl Settings {
pub fn fill_in_from_chain_configs(
&mut self,
src_chain_config: &ChainConfig,
dst_chain_config: &ChainConfig,
) {
if self.max_clock_drift.is_none() {
self.max_clock_drift = Some(calculate_client_state_drift(
&src_chain_config,
&dst_chain_config,
));
}
}
}

/// The client state clock drift must account for destination
/// chain block frequency and clock drift on source and dest.
/// https://github.com/informalsystems/ibc-rs/issues/1445
fn calculate_client_state_drift(
src_chain_config: &ChainConfig,
dst_chain_config: &ChainConfig,
) -> Duration {
src_chain_config.clock_drift + dst_chain_config.clock_drift + dst_chain_config.max_block_time
}
8 changes: 5 additions & 3 deletions relayer/src/chain/handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ use crate::{
keyring::KeyEntry,
};

use super::{tx::TrackedMsgs, HealthCheck, StatusResponse};
use super::client::ClientSettings;
use super::tx::TrackedMsgs;
use super::{HealthCheck, StatusResponse};

mod base;
mod cache;
Expand Down Expand Up @@ -165,7 +167,7 @@ pub enum ChainRequest {

BuildClientState {
height: Height,
dst_config: ChainConfig,
settings: ClientSettings,
reply_to: ReplyTo<AnyClientState>,
},

Expand Down Expand Up @@ -493,7 +495,7 @@ pub trait ChainHandle: Clone + Send + Sync + Serialize + Debug + 'static {
fn build_client_state(
&self,
height: Height,
dst_config: ChainConfig,
settings: ClientSettings,
) -> Result<AnyClientState, Error>;

/// Constructs a consensus state at the given height
Expand Down
6 changes: 3 additions & 3 deletions relayer/src/chain/handle/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ use ibc_proto::ibc::core::connection::v1::QueryClientConnectionsRequest;
use ibc_proto::ibc::core::connection::v1::QueryConnectionsRequest;

use crate::{
chain::{tx::TrackedMsgs, StatusResponse},
chain::{client::ClientSettings, tx::TrackedMsgs, StatusResponse},
config::ChainConfig,
connection::ConnectionMsgType,
error::Error,
Expand Down Expand Up @@ -331,11 +331,11 @@ impl ChainHandle for BaseChainHandle {
fn build_client_state(
&self,
height: Height,
dst_config: ChainConfig,
settings: ClientSettings,
) -> Result<AnyClientState, Error> {
self.send(|reply_to| ChainRequest::BuildClientState {
height,
dst_config,
settings,
reply_to,
})
}
Expand Down
5 changes: 3 additions & 2 deletions relayer/src/chain/handle/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ use ibc_proto::ibc::core::connection::v1::QueryConnectionsRequest;
use serde::{Serialize, Serializer};

use crate::cache::Cache;
use crate::chain::client::ClientSettings;
use crate::chain::handle::{ChainHandle, ChainRequest, Subscription};
use crate::chain::tx::TrackedMsgs;
use crate::chain::{HealthCheck, StatusResponse};
Expand Down Expand Up @@ -313,9 +314,9 @@ impl<Handle: ChainHandle> ChainHandle for CachingChainHandle<Handle> {
fn build_client_state(
&self,
height: Height,
dst_config: ChainConfig,
settings: ClientSettings,
) -> Result<AnyClientState, Error> {
self.inner().build_client_state(height, dst_config)
self.inner().build_client_state(height, settings)
}

/// Constructs a consensus state at the given height
Expand Down
5 changes: 3 additions & 2 deletions relayer/src/chain/handle/counting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ use std::collections::HashMap;
use std::sync::{Arc, RwLock, RwLockReadGuard};
use tracing::debug;

use crate::chain::client::ClientSettings;
use crate::chain::handle::{ChainHandle, ChainRequest, Subscription};
use crate::chain::tx::TrackedMsgs;
use crate::chain::{HealthCheck, StatusResponse};
Expand Down Expand Up @@ -337,10 +338,10 @@ impl<Handle: ChainHandle> ChainHandle for CountingChainHandle<Handle> {
fn build_client_state(
&self,
height: Height,
dst_config: ChainConfig,
options: ClientSettings,
) -> Result<AnyClientState, Error> {
self.inc_metric("build_client_state");
self.inner().build_client_state(height, dst_config)
self.inner().build_client_state(height, options)
}

/// Constructs a consensus state at the given height
Expand Down
24 changes: 19 additions & 5 deletions relayer/src/chain/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ use ibc_proto::ibc::core::connection::v1::{
QueryClientConnectionsRequest, QueryConnectionsRequest,
};

use crate::chain::client::ClientSettings;
use crate::chain::{ChainEndpoint, StatusResponse};
use crate::config::ChainConfig;
use crate::error::Error;
Expand Down Expand Up @@ -350,15 +351,28 @@ impl ChainEndpoint for MockChain {
fn build_client_state(
&self,
height: Height,
dst_config: ChainConfig,
settings: ClientSettings,
) -> Result<Self::ClientState, Error> {
let settings = match settings {
ClientSettings::Cosmos(s) => s,
};
let max_clock_drift = settings
.max_clock_drift
.expect("`fill_in_from_chain_configs` should have been called");
let trusting_period = settings
.trusting_period
.unwrap_or_else(|| self.trusting_period());
let trust_threshold = settings
.trust_threshold
.unwrap_or(self.config.trust_threshold)
.into();

let client_state = TendermintClientState::new(
self.id().clone(),
self.config.trust_threshold.into(),
self.trusting_period(),
trust_threshold,
trusting_period,
self.trusting_period().add(Duration::from_secs(1000)),
// See `calculate_client_state_drift`
self.config.clock_drift + dst_config.clock_drift + dst_config.max_block_time,
max_clock_drift,
height,
ProofSpecs::default(),
vec!["upgrade/upgradedClient".to_string()],
Expand Down
Loading