From b0ec88e6c5aa0e4c6778375ef8ec84d9fbcb5cc2 Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Thu, 1 Apr 2021 16:49:50 +0200 Subject: [PATCH 01/10] Remove light client commands and configuration --- relayer-cli/src/cli_utils.rs | 57 +--- relayer-cli/src/commands.rs | 10 +- relayer-cli/src/commands/create/channel.rs | 17 +- relayer-cli/src/commands/create/connection.rs | 15 +- relayer-cli/src/commands/light.rs | 18 -- relayer-cli/src/commands/light/add.rs | 287 ------------------ relayer-cli/src/commands/light/rm.rs | 173 ----------- relayer-cli/src/commands/tx/channel.rs | 12 +- relayer-cli/src/commands/tx/client.rs | 29 +- relayer-cli/src/commands/tx/connection.rs | 12 +- relayer-cli/src/commands/tx/packet.rs | 19 +- relayer-cli/src/registry.rs | 2 +- relayer/src/chain/cosmos.rs | 18 +- relayer/src/chain/mock.rs | 1 - relayer/src/config.rs | 88 +----- relayer/src/light_client/tendermint.rs | 15 +- 16 files changed, 55 insertions(+), 718 deletions(-) delete mode 100644 relayer-cli/src/commands/light.rs delete mode 100644 relayer-cli/src/commands/light/add.rs delete mode 100644 relayer-cli/src/commands/light/rm.rs diff --git a/relayer-cli/src/cli_utils.rs b/relayer-cli/src/cli_utils.rs index 2bb48c0b80..51c8f3fa42 100644 --- a/relayer-cli/src/cli_utils.rs +++ b/relayer-cli/src/cli_utils.rs @@ -1,7 +1,6 @@ use ibc::ics24_host::identifier::ChainId; use ibc_relayer::chain::runtime::ChainRuntime; use ibc_relayer::chain::CosmosSdkChain; -use ibc_relayer::config::{ChainConfig, StoreConfig}; use ibc_relayer::{chain::handle::ChainHandle, config::Config}; use crate::error::{Error, Kind}; @@ -23,20 +22,8 @@ impl ChainHandlePair { src_chain_id: &ChainId, dst_chain_id: &ChainId, ) -> Result { - Self::spawn_with(Default::default(), config, src_chain_id, dst_chain_id) - } - - /// Spawn the source and destination chain runtime from the configuration and chain identifiers, - /// and return the pair of associated handles. Accepts a `SpawnOptions` argument, which - /// is used to override each chain configuration before spawning its runtime. - pub fn spawn_with( - options: SpawnOptions, - config: &Config, - src_chain_id: &ChainId, - dst_chain_id: &ChainId, - ) -> Result { - let src = spawn_chain_runtime(options.clone(), config, src_chain_id)?; - let dst = spawn_chain_runtime(options, config, dst_chain_id)?; + let src = spawn_chain_runtime(config, src_chain_id)?; + let dst = spawn_chain_runtime(config, dst_chain_id)?; Ok(ChainHandlePair { src, dst }) } @@ -45,18 +32,15 @@ impl ChainHandlePair { /// Spawns a chain runtime from the configuration and given a chain identifier. /// Returns the corresponding handle if successful. pub fn spawn_chain_runtime( - spawn_options: SpawnOptions, config: &Config, chain_id: &ChainId, ) -> Result, Error> { - let mut chain_config = config + let chain_config = config .find_chain(chain_id) .cloned() .ok_or_else(|| format!("missing chain for id ({}) in configuration file", chain_id)) .map_err(|e| Kind::Config.context(e))?; - spawn_options.apply(&mut chain_config); - let chain_res = ChainRuntime::::spawn(chain_config).map_err(|e| Kind::Runtime.context(e)); @@ -64,38 +48,3 @@ pub fn spawn_chain_runtime( Ok(handle) } - -/// Allows override the chain configuration just before -/// spawning a new runtime instance. -/// -/// This is currently only used to override the configured -/// light client store for one-off commands which do not -/// need the disk-based store. -#[derive(Clone, Debug, Default)] -pub struct SpawnOptions { - override_store_config: Option, -} - -impl SpawnOptions { - /// Override the light client store config with the provided config. - pub fn override_store_config(store_config: StoreConfig) -> Self { - Self { - override_store_config: Some(store_config), - } - } - - /// Apply these options to the provided chain configuration. - pub fn apply(&self, chain_config: &mut ChainConfig) { - if let Some(store_config) = &self.override_store_config { - Self::apply_store_config(chain_config, &store_config) - } - } - - fn apply_store_config(chain_config: &mut ChainConfig, store_config: &StoreConfig) { - if let Some(peer_config) = chain_config.peers.as_mut() { - for light_client in &mut peer_config.light_clients { - light_client.store = store_config.clone(); - } - } - } -} diff --git a/relayer-cli/src/commands.rs b/relayer-cli/src/commands.rs index 811f468120..d9f495633a 100644 --- a/relayer-cli/src/commands.rs +++ b/relayer-cli/src/commands.rs @@ -12,15 +12,13 @@ use abscissa_core::{Command, Configurable, FrameworkError, Help, Options, Runnab use crate::config::Config; use self::{ - create::CreateCmds, keys::KeysCmd, light::LightCmd, listen::ListenCmd, query::QueryCmd, - start::StartCmd, start_multi::StartMultiCmd, tx::TxCmd, update::UpdateCmds, - version::VersionCmd, + create::CreateCmds, keys::KeysCmd, listen::ListenCmd, query::QueryCmd, start::StartCmd, + start_multi::StartMultiCmd, tx::TxCmd, update::UpdateCmds, version::VersionCmd, }; mod config; mod create; mod keys; -mod light; mod listen; mod query; mod start; @@ -50,10 +48,6 @@ pub enum CliCmd { #[options(help = "Manage keys in the relayer for each chain")] Keys(KeysCmd), - /// The `light` subcommand - #[options(help = "Basic functionality for managing the light clients")] - Light(LightCmd), - /// The `create` subcommand #[options(help = "Create objects (client, connection, or channel) on chains")] Create(CreateCmds), diff --git a/relayer-cli/src/commands/create/channel.rs b/relayer-cli/src/commands/create/channel.rs index 82a3c7869b..df94458afb 100644 --- a/relayer-cli/src/commands/create/channel.rs +++ b/relayer-cli/src/commands/create/channel.rs @@ -6,11 +6,10 @@ use ibc::ics04_channel::channel::Order; use ibc::ics24_host::identifier::{ChainId, ConnectionId, PortId}; use ibc::Height; use ibc_relayer::channel::Channel; -use ibc_relayer::config::StoreConfig; use ibc_relayer::connection::Connection; use ibc_relayer::foreign_client::ForeignClient; -use crate::cli_utils::{spawn_chain_runtime, ChainHandlePair, SpawnOptions}; +use crate::cli_utils::{spawn_chain_runtime, ChainHandlePair}; use crate::conclude::{exit_with_unrecoverable_error, Output}; use crate::prelude::*; @@ -69,11 +68,9 @@ impl CreateChannelCommand { fn run_using_new_connection(&self, chain_b_id: &ChainId) { let config = app_config(); - let spawn_options = SpawnOptions::override_store_config(StoreConfig::memory()); + let chains = ChainHandlePair::spawn(&config, &self.chain_a_id, chain_b_id) + .unwrap_or_else(exit_with_unrecoverable_error); - let chains = - ChainHandlePair::spawn_with(spawn_options, &config, &self.chain_a_id, chain_b_id) - .unwrap_or_else(exit_with_unrecoverable_error); info!( "Creating new clients, new connection, and a new channel with order {:?} and version {}", self.order, self.version @@ -100,10 +97,8 @@ impl CreateChannelCommand { fn run_reusing_connection(&self) { let config = app_config(); - let spawn_options = SpawnOptions::override_store_config(StoreConfig::memory()); - // Validate & spawn runtime for side a. - let chain_a = spawn_chain_runtime(spawn_options.clone(), &config, &self.chain_a_id) + let chain_a = spawn_chain_runtime(&config, &self.chain_a_id) .unwrap_or_else(exit_with_unrecoverable_error); // Unwrap the identifier of the connection on side a. @@ -130,8 +125,8 @@ impl CreateChannelCommand { .unwrap_or_else(exit_with_unrecoverable_error); // Spawn the runtime for side b. - let chain_b = spawn_chain_runtime(spawn_options, &config, &chain_b_id) - .unwrap_or_else(exit_with_unrecoverable_error); + let chain_b = + spawn_chain_runtime(&config, &chain_b_id).unwrap_or_else(exit_with_unrecoverable_error); // Create the foreign client handles. let client_a = ForeignClient::find(chain_b.clone(), chain_a.clone(), conn_end.client_id()) diff --git a/relayer-cli/src/commands/create/connection.rs b/relayer-cli/src/commands/create/connection.rs index e7cca54b2c..4fd4019ae8 100644 --- a/relayer-cli/src/commands/create/connection.rs +++ b/relayer-cli/src/commands/create/connection.rs @@ -3,11 +3,10 @@ use abscissa_core::{Command, Options, Runnable}; use ibc::ics02_client::client_state::ClientState; use ibc::ics24_host::identifier::{ChainId, ClientId}; use ibc::Height; -use ibc_relayer::config::StoreConfig; use ibc_relayer::connection::Connection; use ibc_relayer::foreign_client::ForeignClient; -use crate::cli_utils::{spawn_chain_runtime, ChainHandlePair, SpawnOptions}; +use crate::cli_utils::{spawn_chain_runtime, ChainHandlePair}; use crate::conclude::{exit_with_unrecoverable_error, Output}; use crate::prelude::*; @@ -60,11 +59,8 @@ impl CreateConnectionCommand { fn run_using_new_clients(&self, chain_b_id: &ChainId) { let config = app_config(); - let spawn_options = SpawnOptions::override_store_config(StoreConfig::memory()); - - let chains = - ChainHandlePair::spawn_with(spawn_options, &config, &self.chain_a_id, chain_b_id) - .unwrap_or_else(exit_with_unrecoverable_error); + let chains = ChainHandlePair::spawn(&config, &self.chain_a_id, chain_b_id) + .unwrap_or_else(exit_with_unrecoverable_error); // Validate the other options. Bail if the CLI was invoked with incompatible options. if self.client_a.is_some() { @@ -99,9 +95,8 @@ impl CreateConnectionCommand { fn run_reusing_clients(&self) { let config = app_config(); - let spawn_options = SpawnOptions::override_store_config(StoreConfig::memory()); // Validate & spawn runtime for chain_a. - let chain_a = match spawn_chain_runtime(spawn_options.clone(), &config, &self.chain_a_id) { + let chain_a = match spawn_chain_runtime(&config, &self.chain_a_id) { Ok(handle) => handle, Err(e) => return Output::error(format!("{}", e)).exit(), }; @@ -131,7 +126,7 @@ impl CreateConnectionCommand { }; // Validate & spawn runtime for chain_b. - let chain_b = match spawn_chain_runtime(spawn_options, &config, &chain_b_id) { + let chain_b = match spawn_chain_runtime(&config, &chain_b_id) { Ok(handle) => handle, Err(e) => return Output::error(format!("{}", e)).exit(), }; diff --git a/relayer-cli/src/commands/light.rs b/relayer-cli/src/commands/light.rs deleted file mode 100644 index ca92b73e8d..0000000000 --- a/relayer-cli/src/commands/light.rs +++ /dev/null @@ -1,18 +0,0 @@ -//! `light` subcommand - -use abscissa_core::{Command, Options, Runnable}; - -mod add; -mod rm; - -/// `light` subcommand -#[derive(Command, Debug, Options, Runnable)] -pub enum LightCmd { - /// The `light add` subcommand - #[options(help = "Add a light client peer for a given chain")] - Add(add::AddCmd), - - /// The `light rm` subcommand - #[options(help = "Remove a light client peer for a given chain")] - Rm(rm::RmCmd), -} diff --git a/relayer-cli/src/commands/light/add.rs b/relayer-cli/src/commands/light/add.rs deleted file mode 100644 index 245128d3ae..0000000000 --- a/relayer-cli/src/commands/light/add.rs +++ /dev/null @@ -1,287 +0,0 @@ -use std::{fmt, io, io::Write, ops::Deref, path::PathBuf}; - -use abscissa_core::{application::fatal_error, error::BoxError, Command, Options, Runnable}; - -use config::StoreConfig; -use ibc::ics24_host::identifier::ChainId; -use ibc_relayer::{ - config, - config::{Config, LightClientConfig, PeersConfig}, - util::block_on, -}; -use tendermint::block::Height; -use tendermint::hash::Hash; -use tendermint_light_client::types::PeerId; -use tendermint_rpc::{Client, HttpClient}; - -use crate::prelude::*; - -#[derive(Command, Debug, Options)] -pub struct AddCmd { - /// RPC network address (required) - #[options(free)] - address: Option, - - /// identifier of the chain (required) - #[options(short = "c")] - chain_id: Option, - - /// path to light client store for this peer (required) - store: Option, - - /// whether this is the primary peer - primary: bool, - - /// allow overriding an existing peer - force: bool, - - /// skip confirmation - yes: bool, - - /// override peer id (optional) - #[options(no_short)] - peer_id: Option, - - /// override height (optional) - #[options(no_short)] - height: Option, - - /// override hash (optional) - #[options(no_short)] - hash: Option, -} - -impl AddCmd { - fn cmd(&self) -> Result<(), BoxError> { - let config = (*app_config()).clone(); - let options = AddOptions::from_cmd(self).map_err(|e| format!("invalid options: {}", e))?; - - options - .validate() - .map_err(|e| format!("invalid options: {}", e))?; - - add(config, options) - } -} - -impl Runnable for AddCmd { - fn run(&self) { - self.cmd() - .unwrap_or_else(|e| fatal_error(app_reader().deref(), &*e)) - } -} - -#[derive(Clone, Debug)] -struct AddOptions { - /// identifier of the chain - chain_id: ChainId, - - /// RPC network address - address: tendermint_rpc::Url, - - /// whether this is the primary peer or not - primary: bool, - - /// path to light client store for this peer - store: PathBuf, - - /// override peer id - override_peer_id: Option, - - /// override height - override_height: Option, - - /// override hash - override_hash: Option, - - /// allow overriding an existing peer - force: bool, - - /// skip confirmation - yes: bool, -} - -impl AddOptions { - fn from_cmd(cmd: &AddCmd) -> Result { - let chain_id = cmd.chain_id.clone().ok_or("missing chain identifier")?; - let address = cmd.address.clone().ok_or("missing RPC network address")?; - let store_path = cmd.store.clone().ok_or("missing store path")?; - - Ok(AddOptions { - chain_id, - address, - store: store_path, - override_peer_id: cmd.peer_id, - override_height: cmd.height, - override_hash: cmd.hash, - primary: cmd.primary, - force: cmd.force, - yes: cmd.yes, - }) - } - - fn validate(&self) -> Result<(), BoxError> { - if !self.store.exists() { - return Err(format!("Store path '{}' does not exists", self.store.display()).into()); - } - - if !self.store.is_dir() { - return Err(format!("Store path '{}' is not a directory", self.store.display()).into()); - } - - Ok(()) - } -} - -#[derive(Debug, Clone)] -pub struct NodeStatus { - chain_id: ChainId, - address: tendermint_rpc::Url, - peer_id: PeerId, - hash: Hash, - height: Height, -} - -impl fmt::Display for NodeStatus { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - writeln!(f, " chain id: {}", self.chain_id)?; - writeln!(f, " address: {}", self.address)?; - writeln!(f, " peer id: {}", self.peer_id)?; - writeln!(f, " height: {}", self.height)?; - writeln!(f, " hash: {}", self.hash)?; - - Ok(()) - } -} - -fn add(mut config: Config, options: AddOptions) -> Result<(), BoxError> { - // Fetch the status from the node - let mut status = fetch_status(options.chain_id.clone(), options.address.clone())?; - - // Override the fetched status with command line arguments, if given - override_status(&mut status, &options); - - // Ask the user for confirmation if --yes was not supplied - if !(options.yes || confirm(&status, options.primary)?) { - return Ok(()); - } - - // Update the in-memory configuration - let new_primary = update_config(options, status.clone(), &mut config)?; - - // Write the updated configuration to disk - let config_path = crate::config::config_path()?; - ibc_relayer::config::store(&config, config_path)?; - - status_ok!( - "Success", - "Added light client:\n{} primary: {}", - status, - status.peer_id == new_primary, - ); - - Ok(()) -} - -fn fetch_status(chain_id: ChainId, address: tendermint_rpc::Url) -> Result { - let rpc_client = HttpClient::new(address.clone())?; - let response = block_on(rpc_client.status())?; - - let peer_id = response.node_info.id; - let height = response.sync_info.latest_block_height; - let hash = response.sync_info.latest_block_hash; - - Ok(NodeStatus { - chain_id, - address, - peer_id, - hash, - height, - }) -} - -fn override_status(status: &mut NodeStatus, options: &AddOptions) { - if let Some(peer_id) = options.override_peer_id { - status.peer_id = peer_id; - } - - if let Some(height) = options.override_height { - status.height = height; - } - - if let Some(hash) = options.override_hash { - status.hash = hash; - } -} - -fn confirm(status: &NodeStatus, primary: bool) -> Result { - print!("Light client configuration:\n{}", status); - println!(" primary: {}", primary); - - loop { - print!("\n? Do you want to add a new light client with these trust options? (y/n) > "); - io::stdout().flush()?; // need to flush stdout since stdout is often line-buffered - - let mut choice = String::new(); - io::stdin().read_line(&mut choice)?; - - match choice.trim_end() { - "y" | "yes" => return Ok(true), - "n" | "no" => return Ok(false), - _ => continue, - } - } -} - -fn update_config( - options: AddOptions, - status: NodeStatus, - config: &mut Config, -) -> Result { - let chain_config = config - .find_chain_mut(&options.chain_id) - .ok_or_else(|| format!("could not find config for chain: {}", options.chain_id))?; - - let peers_config = chain_config.peers.get_or_insert_with(|| PeersConfig { - primary: status.peer_id, - light_clients: vec![], - }); - - // Check if the given peer exists already, in which case throw an error except if the - // --force flag is set. - let peer_exists = peers_config.light_client(status.peer_id).is_some(); - if peer_exists && !options.force { - return Err(format!( - "a peer with id {} already exists, remove it first \ - or pass the --force flag to override it", - status.peer_id - ) - .into()); - } - - let light_client_config = LightClientConfig { - peer_id: status.peer_id, - address: status.address.clone(), - timeout: config::default::timeout(), - trusted_header_hash: status.hash, - trusted_height: status.height, - store: StoreConfig::Disk { - path: options.store.join(status.peer_id.to_string()), - }, - }; - - if peer_exists { - // Filter out the light client config with the specified peer id - peers_config - .light_clients - .retain(|p| p.peer_id != status.peer_id); - } - - peers_config.light_clients.push(light_client_config); - - if options.primary { - peers_config.primary = status.peer_id; - } - - Ok(peers_config.primary) -} diff --git a/relayer-cli/src/commands/light/rm.rs b/relayer-cli/src/commands/light/rm.rs deleted file mode 100644 index dc2bbf8628..0000000000 --- a/relayer-cli/src/commands/light/rm.rs +++ /dev/null @@ -1,173 +0,0 @@ -use std::{io, io::Write, ops::Deref}; - -use abscissa_core::{application::fatal_error, error::BoxError, Command, Options, Runnable}; -use tendermint_light_client::types::PeerId; - -use ibc::ics24_host::identifier::ChainId; -use ibc_relayer::config::PeersConfig; - -use crate::conclude::Output; -use crate::prelude::*; - -#[derive(Command, Debug, Options)] -pub struct RmCmd { - /// identifiers of peers to remove - #[options(free)] - peer_id: Vec, - - /// identifier of the chain to remove peers from - #[options(short = "c")] - chain_id: Option, - - /// force removal of primary peer - #[options(short = "f")] - force: bool, - - /// remove all peers, implies --force - #[options(no_short)] - all: bool, - - /// skip confirmation - yes: bool, -} - -#[derive(Clone, Debug)] -struct RmOptions { - /// identifier of the chain to remove peers from - chain_id: ChainId, - - /// identifiers of peers to remove - peer_ids: Vec, - - /// remove all peers, implies --force - all: bool, - - /// force removal of primary peer - force: bool, - - /// skip confirmation - yes: bool, -} - -impl RmOptions { - fn from_cmd(cmd: &RmCmd) -> Result { - let chain_id = cmd.chain_id.clone().ok_or("missing chain identifier")?; - let peer_ids = if !cmd.all && cmd.peer_id.is_empty() { - return Err("missing peer identifier".into()); - } else { - cmd.peer_id.clone() - }; - - Ok(RmOptions { - chain_id, - peer_ids, - all: cmd.all, - yes: cmd.yes, - force: cmd.force, - }) - } -} - -impl Runnable for RmCmd { - fn run(&self) { - self.cmd() - .unwrap_or_else(|e| fatal_error(app_reader().deref(), &*e)) - } -} - -impl RmCmd { - fn cmd(&self) -> Result<(), BoxError> { - let options = RmOptions::from_cmd(self).map_err(|e| format!("invalid options: {}", e))?; - let mut config = (*app_config()).clone(); - - let chain_config = config - .find_chain_mut(&options.chain_id) - .ok_or_else(|| format!("could not find config for chain: {}", options.chain_id))?; - - let mut peers_config = chain_config - .peers - .as_mut() - .ok_or_else(|| format!("no peers configured for chain: {}", options.chain_id))?; - - let rmd_peers = if options.all && (options.yes || confirm(&options.chain_id)?) { - let removed_peers = get_all_peer_ids(&peers_config); - chain_config.peers = None; - - removed_peers - } else { - let mut res: Vec = vec![]; - for peer_id in options.peer_ids { - let removed_peer = remove_peer(&mut peers_config, peer_id, options.force)?; - res.push(removed_peer.to_string()); - } - - res - }; - - let config_path = crate::config::config_path()?; - ibc_relayer::config::store(&config, config_path)?; - - Output::success(format!("Removed light client peer(s) '{:?}'", rmd_peers)).exit(); - - Ok(()) - } -} - -fn remove_peer( - peers_config: &mut PeersConfig, - peer_id: PeerId, - force: bool, -) -> Result { - // Check if the given peer actually exists already, if not throw an error. - let peer_exists = peers_config.light_client(peer_id).is_some(); - if !peer_exists { - return Err(format!("cannot find peer: {}", peer_id).into()); - } - - // Only allow remove the primary peer if the --force option is set - let removed_primary = peers_config.primary == peer_id; - if removed_primary && !force { - return Err("cannot remove primary peer, pass --force flag to force removal".into()); - } - - // Filter out the light client config with the specified peer id - peers_config.light_clients.retain(|p| p.peer_id != peer_id); - - // If the peer we removed was the primary peer, use the next available peer as the primary, - // if any. - if removed_primary { - if let Some(new_primary) = peers_config.light_clients.first() { - peers_config.primary = new_primary.peer_id; - } - } - - Ok(peer_id) -} - -fn get_all_peer_ids(peers_config: &PeersConfig) -> Vec { - peers_config - .light_clients - .iter() - .map(|c| c.peer_id.to_string()) - .collect() -} - -fn confirm(chain_id: &ChainId) -> Result { - loop { - print!( - "\n? Do you really want to remove all peers for chain '{}'? (y/n) > ", - chain_id - ); - - io::stdout().flush()?; // need to flush stdout since stdout is often line-buffered - - let mut choice = String::new(); - io::stdin().read_line(&mut choice)?; - - match choice.trim_end() { - "y" | "yes" => return Ok(true), - "n" | "no" => return Ok(false), - _ => continue, - } - } -} diff --git a/relayer-cli/src/commands/tx/channel.rs b/relayer-cli/src/commands/tx/channel.rs index 0931c2b06f..914f78c52c 100644 --- a/relayer-cli/src/commands/tx/channel.rs +++ b/relayer-cli/src/commands/tx/channel.rs @@ -6,9 +6,8 @@ use ibc::ics04_channel::channel::Order; use ibc::ics24_host::identifier::{ChainId, ChannelId, ClientId, ConnectionId, PortId}; use ibc::Height; use ibc_relayer::channel::{Channel, ChannelSide}; -use ibc_relayer::config::StoreConfig; -use crate::cli_utils::{ChainHandlePair, SpawnOptions}; +use crate::cli_utils::ChainHandlePair; use crate::conclude::Output; use crate::error::{Error, Kind}; use crate::prelude::*; @@ -17,13 +16,8 @@ macro_rules! tx_chan_cmd { ($dbg_string:literal, $func:ident, $self:expr, $chan:expr) => { let config = app_config(); - let spawn_options = SpawnOptions::override_store_config(StoreConfig::memory()); - let chains = match ChainHandlePair::spawn_with( - spawn_options, - &config, - &$self.src_chain_id, - &$self.dst_chain_id, - ) { + let chains = match ChainHandlePair::spawn(&config, &$self.src_chain_id, &$self.dst_chain_id) + { Ok(chains) => chains, Err(e) => return Output::error(format!("{}", e)).exit(), }; diff --git a/relayer-cli/src/commands/tx/client.rs b/relayer-cli/src/commands/tx/client.rs index 38b0b3a209..8f6701a978 100644 --- a/relayer-cli/src/commands/tx/client.rs +++ b/relayer-cli/src/commands/tx/client.rs @@ -3,11 +3,10 @@ use tracing::info; use ibc::events::IbcEvent; use ibc::ics24_host::identifier::{ChainId, ClientId}; -use ibc_relayer::config::StoreConfig; use ibc_relayer::foreign_client::ForeignClient; use crate::application::app_config; -use crate::cli_utils::{ChainHandlePair, SpawnOptions}; +use crate::cli_utils::ChainHandlePair; use crate::conclude::{exit_with_unrecoverable_error, Output}; use crate::error::{Error, Kind}; @@ -26,13 +25,7 @@ impl Runnable for TxCreateClientCmd { fn run(&self) { let config = app_config(); - let spawn_options = SpawnOptions::override_store_config(StoreConfig::memory()); - let chains = match ChainHandlePair::spawn_with( - spawn_options, - &config, - &self.src_chain_id, - &self.dst_chain_id, - ) { + let chains = match ChainHandlePair::spawn(&config, &self.src_chain_id, &self.dst_chain_id) { Ok(chains) => chains, Err(e) => return Output::error(format!("{}", e)).exit(), }; @@ -75,13 +68,7 @@ impl Runnable for TxUpdateClientCmd { fn run(&self) { let config = app_config(); - let spawn_options = SpawnOptions::override_store_config(StoreConfig::memory()); - let chains = match ChainHandlePair::spawn_with( - spawn_options, - &config, - &self.src_chain_id, - &self.dst_chain_id, - ) { + let chains = match ChainHandlePair::spawn(&config, &self.src_chain_id, &self.dst_chain_id) { Ok(chains) => chains, Err(e) => return Output::error(format!("{}", e)).exit(), }; @@ -127,14 +114,8 @@ impl Runnable for TxUpgradeClientCmd { fn run(&self) { let config = app_config(); - let spawn_options = SpawnOptions::override_store_config(StoreConfig::memory()); - let chains = ChainHandlePair::spawn_with( - spawn_options, - &config, - &self.src_chain_id, - &self.dst_chain_id, - ) - .unwrap_or_else(exit_with_unrecoverable_error); + let chains = ChainHandlePair::spawn(&config, &self.src_chain_id, &self.dst_chain_id) + .unwrap_or_else(exit_with_unrecoverable_error); info!("Started the chain runtimes"); diff --git a/relayer-cli/src/commands/tx/connection.rs b/relayer-cli/src/commands/tx/connection.rs index 702ff36906..161416cf32 100644 --- a/relayer-cli/src/commands/tx/connection.rs +++ b/relayer-cli/src/commands/tx/connection.rs @@ -2,10 +2,9 @@ use abscissa_core::{Command, Options, Runnable}; use ibc::events::IbcEvent; use ibc::ics24_host::identifier::{ChainId, ClientId, ConnectionId}; -use ibc_relayer::config::StoreConfig; use ibc_relayer::connection::{Connection, ConnectionSide}; -use crate::cli_utils::{ChainHandlePair, SpawnOptions}; +use crate::cli_utils::ChainHandlePair; use crate::conclude::Output; use crate::error::{Error, Kind}; use crate::prelude::*; @@ -14,13 +13,8 @@ macro_rules! conn_open_cmd { ($dbg_string:literal, $func:ident, $self:expr, $conn:expr) => { let config = app_config(); - let spawn_options = SpawnOptions::override_store_config(StoreConfig::memory()); - let chains = match ChainHandlePair::spawn_with( - spawn_options, - &config, - &$self.src_chain_id, - &$self.dst_chain_id, - ) { + let chains = match ChainHandlePair::spawn(&config, &$self.src_chain_id, &$self.dst_chain_id) + { Ok(chains) => chains, Err(e) => return Output::error(format!("{}", e)).exit(), }; diff --git a/relayer-cli/src/commands/tx/packet.rs b/relayer-cli/src/commands/tx/packet.rs index bf765a6df9..d31ad2e0be 100644 --- a/relayer-cli/src/commands/tx/packet.rs +++ b/relayer-cli/src/commands/tx/packet.rs @@ -2,10 +2,9 @@ use abscissa_core::{Command, Options, Runnable}; use ibc::events::IbcEvent; use ibc::ics24_host::identifier::{ChainId, ChannelId, PortId}; -use ibc_relayer::config::StoreConfig; use ibc_relayer::link::{Link, LinkParameters}; -use crate::cli_utils::{ChainHandlePair, SpawnOptions}; +use crate::cli_utils::ChainHandlePair; use crate::conclude::Output; use crate::error::{Error, Kind}; use crate::prelude::*; @@ -29,13 +28,7 @@ impl Runnable for TxRawPacketRecvCmd { fn run(&self) { let config = app_config(); - let spawn_options = SpawnOptions::override_store_config(StoreConfig::memory()); - let chains = match ChainHandlePair::spawn_with( - spawn_options, - &config, - &self.src_chain_id, - &self.dst_chain_id, - ) { + let chains = match ChainHandlePair::spawn(&config, &self.src_chain_id, &self.dst_chain_id) { Ok(chains) => chains, Err(e) => return Output::error(format!("{}", e)).exit(), }; @@ -79,13 +72,7 @@ impl Runnable for TxRawPacketAckCmd { fn run(&self) { let config = app_config(); - let spawn_options = SpawnOptions::override_store_config(StoreConfig::memory()); - let chains = match ChainHandlePair::spawn_with( - spawn_options, - &config, - &self.src_chain_id, - &self.dst_chain_id, - ) { + let chains = match ChainHandlePair::spawn(&config, &self.src_chain_id, &self.dst_chain_id) { Ok(chains) => chains, Err(e) => return Output::error(format!("{}", e)).exit(), }; diff --git a/relayer-cli/src/registry.rs b/relayer-cli/src/registry.rs index eaf8a8f4d0..5f0b395448 100644 --- a/relayer-cli/src/registry.rs +++ b/relayer-cli/src/registry.rs @@ -30,7 +30,7 @@ impl<'a> Registry<'a> { /// return its handle. pub fn get_or_spawn(&mut self, chain_id: &ChainId) -> Result, Error> { if !self.handles.contains_key(chain_id) { - let handle = spawn_chain_runtime(Default::default(), &self.config, chain_id)?; + let handle = spawn_chain_runtime(&self.config, chain_id)?; self.handles.insert(chain_id.clone(), handle); } diff --git a/relayer/src/chain/cosmos.rs b/relayer/src/chain/cosmos.rs index dce44693fd..d0dba523f3 100644 --- a/relayer/src/chain/cosmos.rs +++ b/relayer/src/chain/cosmos.rs @@ -62,7 +62,7 @@ use crate::config::ChainConfig; use crate::error::{Error, Kind}; use crate::event::monitor::{EventBatch, EventMonitor}; use crate::keyring::store::{KeyEntry, KeyRing, KeyRingOperations, StoreBackend}; -use crate::light_client::tendermint::LightClient as TMLightClient; +use crate::light_client::tendermint::LightClient as TmLightClient; use crate::light_client::LightClient; use super::Chain; @@ -320,7 +320,7 @@ impl Chain for CosmosSdkChain { .map_err(|e| Kind::Rpc(config.rpc_addr.clone()).context(e))?; // Initialize key store and load key - let key_store = KeyRing::init(StoreBackend::Test, config.clone()) + let keybase = KeyRing::init(StoreBackend::Test, config.clone()) .map_err(|e| Kind::KeyBase.context(e))?; let grpc_addr = @@ -329,16 +329,26 @@ impl Chain for CosmosSdkChain { Ok(Self { rt, config, - keybase: key_store, + keybase, rpc_client, grpc_addr, }) } fn init_light_client(&self) -> Result>, Error> { + use tendermint_light_client::types::PeerId; + crate::time!("init_light_client"); - let light_client = TMLightClient::from_config(&self.config)?; + let peer_id: PeerId = self + .rt + .block_on(self.rpc_client.status()) + .map(|s| s.node_info.id) + .map_err(|e| Kind::Rpc(self.config.rpc_addr.clone()).context(e))?; + + let timeout = Duration::from_secs(10); // TODO: Get from global config + let light_client = TmLightClient::from_config(&self.config, peer_id, Some(timeout))?; + Ok(Box::new(light_client)) } diff --git a/relayer/src/chain/mock.rs b/relayer/src/chain/mock.rs index ee9bd48d24..36b9e675ec 100644 --- a/relayer/src/chain/mock.rs +++ b/relayer/src/chain/mock.rs @@ -350,7 +350,6 @@ pub mod test_utils { clock_drift: Duration::from_secs(5), trusting_period: Duration::from_secs(14 * 24 * 60 * 60), // 14 days trust_threshold: Default::default(), - peers: None, } } } diff --git a/relayer/src/config.rs b/relayer/src/config.rs index 66f0d8fb2c..d5b049808d 100644 --- a/relayer/src/config.rs +++ b/relayer/src/config.rs @@ -1,16 +1,9 @@ //! Relayer configuration -use std::{ - fs, - fs::File, - io::Write, - path::{Path, PathBuf}, - time::Duration, -}; +use std::{fs, fs::File, io::Write, path::Path, time::Duration}; use serde_derive::{Deserialize, Serialize}; -use tendermint::Hash; -use tendermint_light_client::types::{Height, PeerId, TrustThreshold}; +use tendermint_light_client::types::TrustThreshold; use ibc::ics24_host::identifier::{ChainId, PortId}; @@ -118,34 +111,6 @@ pub struct ChainConfig { pub trusting_period: Duration, #[serde(default)] pub trust_threshold: TrustThreshold, - - // initially empty, to configure with the `light add/rm` commands - #[serde(skip_serializing_if = "Option::is_none")] - pub peers: Option, -} - -impl ChainConfig { - pub fn primary(&self) -> Option<&LightClientConfig> { - let peers = self.peers.as_ref()?; - peers.light_client(peers.primary) - } - - pub fn light_client(&self, id: PeerId) -> Option<&LightClientConfig> { - let peers = self.peers.as_ref()?; - peers.light_client(id) - } - - pub fn witnesses(&self) -> Option> { - let peers = self.peers.as_ref()?; - - Some( - peers - .light_clients - .iter() - .filter(|p| p.peer_id != peers.primary) - .collect(), - ) - } } #[derive(Clone, Debug, Deserialize, Serialize)] @@ -161,55 +126,6 @@ pub struct RelayPath { pub b_port: PortId, } -#[derive(Clone, Debug, Deserialize, Serialize)] -pub struct PeersConfig { - pub primary: PeerId, - pub light_clients: Vec, -} - -impl PeersConfig { - pub fn light_client(&self, id: PeerId) -> Option<&LightClientConfig> { - self.light_clients.iter().find(|p| p.peer_id == id) - } - - pub fn light_client_mut(&mut self, id: PeerId) -> Option<&mut LightClientConfig> { - self.light_clients.iter_mut().find(|p| p.peer_id == id) - } -} - -#[derive(Clone, Debug, Deserialize, Serialize)] -pub struct LightClientConfig { - pub peer_id: PeerId, - pub address: tendermint_rpc::Url, - #[serde(default = "default::timeout", with = "humantime_serde")] - pub timeout: Duration, - pub trusted_header_hash: Hash, - pub trusted_height: Height, - pub store: StoreConfig, -} - -#[derive(Clone, Debug, Deserialize, Serialize)] -#[serde(tag = "type")] -pub enum StoreConfig { - #[serde(rename = "disk")] - Disk { path: PathBuf }, - #[serde(rename = "memory")] - Memory { - #[serde(skip)] - dummy: (), - }, -} - -impl StoreConfig { - pub fn disk(path: PathBuf) -> Self { - Self::Disk { path } - } - - pub fn memory() -> Self { - Self::Memory { dummy: () } - } -} - /// Attempt to load and parse the TOML config file as a `Config`. pub fn parse(path: impl AsRef) -> Result { let config_toml = diff --git a/relayer/src/light_client/tendermint.rs b/relayer/src/light_client/tendermint.rs index 239032b776..4226e7820c 100644 --- a/relayer/src/light_client/tendermint.rs +++ b/relayer/src/light_client/tendermint.rs @@ -1,4 +1,5 @@ use std::convert::TryFrom; +use std::time::Duration; use tendermint_rpc as rpc; @@ -56,19 +57,19 @@ impl super::LightClient for LightClient { } impl LightClient { - pub fn from_config(config: &ChainConfig) -> Result { + pub fn from_config( + config: &ChainConfig, + peer_id: PeerId, + timeout: Option, + ) -> Result { let rpc_client = rpc::HttpClient::new(config.rpc_addr.clone()) .map_err(|e| error::Kind::LightClient(config.rpc_addr.to_string()).context(e))?; - let peer = config.primary().ok_or_else(|| { - error::Kind::LightClient(config.rpc_addr.to_string()).context("no primary peer") - })?; - - let io = components::io::ProdIo::new(peer.peer_id, rpc_client, Some(peer.timeout)); + let io = components::io::ProdIo::new(peer_id, rpc_client, timeout); Ok(Self { chain_id: config.id.clone(), - peer_id: peer.peer_id, + peer_id, io, }) } From 9d2693332f3cb545b23b31f34b1e1373fa7839d3 Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Thu, 1 Apr 2021 17:02:21 +0200 Subject: [PATCH 02/10] Remove light client init code in scripts --- ci/e2e.sh | 24 ------------------------ scripts/init-clients | 27 --------------------------- 2 files changed, 51 deletions(-) diff --git a/ci/e2e.sh b/ci/e2e.sh index aff85b07af..6e9c037f05 100755 --- a/ci/e2e.sh +++ b/ci/e2e.sh @@ -33,30 +33,6 @@ echo "Add keys for chains" echo "-----------------------------------------------------------------------------------------------------------------" hermes -c "$CONFIG_PATH" keys add "$CHAIN_A" key_seed_"$CHAIN_A".json hermes -c "$CONFIG_PATH" keys add "$CHAIN_B" key_seed_"$CHAIN_B".json -echo "-----------------------------------------------------------------------------------------------------------------" -echo "Set the primary peers for clients on each chain " -echo "-----------------------------------------------------------------------------------------------------------------" -LIGHT_ADD_CHAIN_A="hermes -c $CONFIG_PATH light add http://$CHAIN_A:$CHAIN_A_PORT -c $CHAIN_A -s $CHAIN_A_HOME -p -y -f" -echo "Executing: $LIGHT_ADD_CHAIN_A" -bash -c "$LIGHT_ADD_CHAIN_A" -sleep 2 -echo "-----------------------------------------------------------------------------------------------------------------" -LIGHT_ADD_CHAIN_B="hermes -c $CONFIG_PATH light add http://$CHAIN_B:$CHAIN_B_PORT -c $CHAIN_B -s $CHAIN_B_HOME -p -y -f" -echo "Executing: $LIGHT_ADD_CHAIN_B" -bash -c "$LIGHT_ADD_CHAIN_B" -sleep 2 -echo "-----------------------------------------------------------------------------------------------------------------" -echo "Set the secondary peers for clients on each chain " -echo "-----------------------------------------------------------------------------------------------------------------" -LIGHT_ADD_CHAIN_A_PEER="hermes -c $CONFIG_PATH light add http://$CHAIN_A:$CHAIN_A_PORT -c $CHAIN_A -s $CHAIN_A_HOME --peer-id 17D46D8C1576A79203A6733F63B2C9B7235DD559 -y" -echo "Executing: $LIGHT_ADD_CHAIN_A_PEER" -bash -c "$LIGHT_ADD_CHAIN_A_PEER" -sleep 2 -echo "-----------------------------------------------------------------------------------------------------------------" -LIGHT_ADD_CHAIN_B_PEER="hermes -c $CONFIG_PATH light add http://$CHAIN_B:$CHAIN_B_PORT -c $CHAIN_B -s $CHAIN_B_HOME --peer-id A885BB3D3DFF6101188B462466AE926E7A6CD51E -y" -echo "Executing: $LIGHT_ADD_CHAIN_B_PEER" -bash -c "$LIGHT_ADD_CHAIN_B_PEER" -sleep 2 echo "=================================================================================================================" echo " END-TO-END TESTS " diff --git a/scripts/init-clients b/scripts/init-clients index 5843247686..27dbcd858f 100755 --- a/scripts/init-clients +++ b/scripts/init-clients @@ -68,33 +68,6 @@ CHAIN_2_RPC_ADDR="http://127.0.0.1:$CHAIN_2_RPC_PORT" echo "Building the Rust relayer..." cargo build -q -# cleanup the client entries from config -echo "Removing light client peers from configuration..." -cargo run -q --bin hermes -- -c "$CONFIG_FILE" light rm -c "$CHAIN_0_ID" --all -y || true -cargo run -q --bin hermes -- -c "$CONFIG_FILE" light rm -c "$CHAIN_1_ID" --all -y || true - -if [ -n "$CHAIN_2_ID" ]; then - cargo run -q --bin hermes -- -c "$CONFIG_FILE" light rm -c "$CHAIN_2_ID" --all -y || true -fi - -# set the primary peers for clients on each chain -echo "Adding primary peers to light client configuration..." -cargo run -q --bin hermes -- -c "$CONFIG_FILE" light add $CHAIN_0_RPC_ADDR -c "$CHAIN_0_ID" -f -p -s "$GAIA_DATA/$CHAIN_0_ID/data" -y -cargo run -q --bin hermes -- -c "$CONFIG_FILE" light add $CHAIN_1_RPC_ADDR -c "$CHAIN_1_ID" -f -p -s "$GAIA_DATA/$CHAIN_1_ID/data" -y - -if [ -n "$CHAIN_2_ID" ]; then - cargo run -q --bin hermes -- -c "$CONFIG_FILE" light add $CHAIN_2_RPC_ADDR -c "$CHAIN_2_ID" -f -p -s "$GAIA_DATA/$CHAIN_2_ID/data" -y -fi - -# set the secondary peers for clients on each chain -echo "Adding secondary peers to light client configuration..." -cargo run -q --bin hermes -- -c "$CONFIG_FILE" light add $CHAIN_0_RPC_ADDR -c "$CHAIN_0_ID" -s "$GAIA_DATA/$CHAIN_0_ID/data" -y --peer-id 2427F8D914A6862279B3326FA64F76E3BC06DB2E -cargo run -q --bin hermes -- -c "$CONFIG_FILE" light add $CHAIN_1_RPC_ADDR -c "$CHAIN_1_ID" -s "$GAIA_DATA/$CHAIN_1_ID/data" -y --peer-id A885BB3D3DFF6101188B462466AE926E7A6CD51E - -if [ -n "$CHAIN_2_ID" ]; then - cargo run -q --bin hermes -- -c "$CONFIG_FILE" light add $CHAIN_2_RPC_ADDR -c "$CHAIN_2_ID" -s "$GAIA_DATA/$CHAIN_2_ID/data" -y --peer-id 08B4625466AE926E7A5BB3D3DFF611E6CD118A88 -fi - # add the key seeds to the keyring of each chain echo "Importing keys..." cargo run -q --bin hermes -- -c "$CONFIG_FILE" keys add "$CHAIN_0_ID" "$GAIA_DATA/$CHAIN_0_ID/key_seed.json" From 2ef5a34e805a70a719773e2787b70a76fe4b9624 Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Thu, 1 Apr 2021 18:42:19 +0200 Subject: [PATCH 03/10] Update the changelog --- CHANGELOG.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c549b53b8..53f95ffc7e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -60,10 +60,11 @@ - `MsgConnectionOpenAck.counterparty_connection_id` is now a `ConnectionId` instead of an `Option`([#700]) - [ibc-relayer] - - [nothing yet] + - Remove the light client configuration from the global configuration ([#793]) - [ibc-relayer-cli] - - [nothing yet] + - Remove the light add and light rm commands ([#793]) + [#352]: https://github.com/informalsystems/ibc-rs/issues/352 [#357]: https://github.com/informalsystems/ibc-rs/issues/357 @@ -89,6 +90,7 @@ [#761]: https://github.com/informalsystems/ibc-rs/issues/761 [#772]: https://github.com/informalsystems/ibc-rs/issues/772 [#770]: https://github.com/informalsystems/ibc-rs/issues/770 +[#793]: https://github.com/informalsystems/ibc-rs/pull/793 ## v0.1.1 From 6a8de5bd2f5117e8c963abdf51dbf8a29f001bf5 Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Tue, 6 Apr 2021 16:16:17 +0200 Subject: [PATCH 04/10] Use rpc_timeout field from chain config --- relayer/src/chain/cosmos.rs | 3 +-- relayer/src/chain/mock.rs | 1 + relayer/src/config.rs | 8 +++----- relayer/src/light_client/tendermint.rs | 16 +++++++--------- 4 files changed, 12 insertions(+), 16 deletions(-) diff --git a/relayer/src/chain/cosmos.rs b/relayer/src/chain/cosmos.rs index d0dba523f3..8c50a11598 100644 --- a/relayer/src/chain/cosmos.rs +++ b/relayer/src/chain/cosmos.rs @@ -346,8 +346,7 @@ impl Chain for CosmosSdkChain { .map(|s| s.node_info.id) .map_err(|e| Kind::Rpc(self.config.rpc_addr.clone()).context(e))?; - let timeout = Duration::from_secs(10); // TODO: Get from global config - let light_client = TmLightClient::from_config(&self.config, peer_id, Some(timeout))?; + let light_client = TmLightClient::from_config(&self.config, peer_id)?; Ok(Box::new(light_client)) } diff --git a/relayer/src/chain/mock.rs b/relayer/src/chain/mock.rs index 36b9e675ec..7653ee290d 100644 --- a/relayer/src/chain/mock.rs +++ b/relayer/src/chain/mock.rs @@ -339,6 +339,7 @@ pub mod test_utils { rpc_addr: "http://127.0.0.1:26656".parse().unwrap(), grpc_addr: "http://127.0.0.1:9090".parse().unwrap(), websocket_addr: "ws://127.0.0.1:26656/websocket".parse().unwrap(), + rpc_timeout: crate::config::default::rpc_timeout(), account_prefix: "".to_string(), key_name: "".to_string(), store_prefix: "".to_string(), diff --git a/relayer/src/config.rs b/relayer/src/config.rs index d5b049808d..d02b106659 100644 --- a/relayer/src/config.rs +++ b/relayer/src/config.rs @@ -13,7 +13,7 @@ use crate::error; pub mod default { use super::*; - pub fn timeout() -> Duration { + pub fn rpc_timeout() -> Duration { Duration::from_secs(10) } @@ -70,9 +70,6 @@ impl Default for Strategy { #[derive(Clone, Debug, Deserialize, Serialize)] pub struct GlobalConfig { - #[serde(default = "default::timeout", with = "humantime_serde")] - pub timeout: Duration, - #[serde(default)] pub strategy: Strategy, @@ -84,7 +81,6 @@ pub struct GlobalConfig { impl Default for GlobalConfig { fn default() -> Self { Self { - timeout: default::timeout(), strategy: Strategy::default(), log_level: "info".to_string(), } @@ -97,6 +93,8 @@ pub struct ChainConfig { pub rpc_addr: tendermint_rpc::Url, pub websocket_addr: tendermint_rpc::Url, pub grpc_addr: tendermint_rpc::Url, + #[serde(default = "default::rpc_timeout", with = "humantime_serde")] + pub rpc_timeout: Duration, pub account_prefix: String, pub key_name: String, pub store_prefix: String, diff --git a/relayer/src/light_client/tendermint.rs b/relayer/src/light_client/tendermint.rs index 4226e7820c..f5648b4c6b 100644 --- a/relayer/src/light_client/tendermint.rs +++ b/relayer/src/light_client/tendermint.rs @@ -1,5 +1,4 @@ use std::convert::TryFrom; -use std::time::Duration; use tendermint_rpc as rpc; @@ -13,8 +12,11 @@ use tendermint_light_client::{ types::{LightBlock, PeerId, Status}, }; -use ibc::{downcast, ics02_client::client_state::AnyClientState}; -use ibc::{ics02_client::client_type::ClientType, ics24_host::identifier::ChainId}; +use ibc::{ + downcast, + ics02_client::{client_state::AnyClientState, client_type::ClientType}, + ics24_host::identifier::ChainId, +}; use crate::{ chain::CosmosSdkChain, @@ -57,15 +59,11 @@ impl super::LightClient for LightClient { } impl LightClient { - pub fn from_config( - config: &ChainConfig, - peer_id: PeerId, - timeout: Option, - ) -> Result { + pub fn from_config(config: &ChainConfig, peer_id: PeerId) -> Result { let rpc_client = rpc::HttpClient::new(config.rpc_addr.clone()) .map_err(|e| error::Kind::LightClient(config.rpc_addr.to_string()).context(e))?; - let io = components::io::ProdIo::new(peer_id, rpc_client, timeout); + let io = components::io::ProdIo::new(peer_id, rpc_client, Some(config.rpc_timeout)); Ok(Self { chain_id: config.id.clone(), From d3cb2d9fe652e41f88584e9f1a04b5aec47d8c34 Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Tue, 6 Apr 2021 16:30:28 +0200 Subject: [PATCH 05/10] Update config files and ADRs --- ci/simple_config.toml | 3 +- config.toml | 3 +- config_example.toml | 3 +- docs/architecture/adr-002-ibc-relayer.md | 34 +++++++++++-------- .../adr-006-hermes-v0.2-usecases.md | 1 - relayer-cli/tests/fixtures/two_chains.toml | 33 ++---------------- .../config/fixtures/relayer_conf_example.toml | 3 +- .../tests/config/fixtures/simple_config.toml | 9 ++--- 8 files changed, 33 insertions(+), 56 deletions(-) diff --git a/ci/simple_config.toml b/ci/simple_config.toml index 7aaf2aff1d..35be457c28 100644 --- a/ci/simple_config.toml +++ b/ci/simple_config.toml @@ -1,5 +1,4 @@ [global] -timeout = '10s' strategy = 'naive' log_level = 'info' @@ -8,6 +7,7 @@ id = 'ibc-0' rpc_addr = 'http://ibc-0:26657' grpc_addr = 'http://ibc-0:9090' websocket_addr = 'ws://ibc-0:26657/websocket' +rpc_timeout = '10s' account_prefix = 'cosmos' key_name = 'testkey' store_prefix = 'ibc' @@ -22,6 +22,7 @@ id = 'ibc-1' rpc_addr = 'http://ibc-1:26657' grpc_addr = 'http://ibc-1:9090' websocket_addr = 'ws://ibc-1:26657/websocket' +rpc_timeout = '10s' account_prefix = 'cosmos' key_name = 'testkey' store_prefix = 'ibc' diff --git a/config.toml b/config.toml index fc677da33d..2904ee82d5 100644 --- a/config.toml +++ b/config.toml @@ -1,5 +1,4 @@ [global] -timeout = '10s' strategy = 'naive' log_level = 'error' @@ -8,6 +7,7 @@ id = 'ibc-0' rpc_addr = 'http://127.0.0.1:26657' grpc_addr = 'http://127.0.0.1:9090' websocket_addr = 'ws://127.0.0.1:26657/websocket' +rpc_timeout = '10s' account_prefix = 'cosmos' key_name = 'testkey' store_prefix = 'ibc' @@ -26,6 +26,7 @@ id = 'ibc-1' rpc_addr = 'http://127.0.0.1:26557' grpc_addr = 'http://127.0.0.1:9091' websocket_addr = 'ws://127.0.0.1:26557/websocket' +rpc_timeout = '10s' account_prefix = 'cosmos' key_name = 'testkey' store_prefix = 'ibc' diff --git a/config_example.toml b/config_example.toml index 0685f82317..01dfa1e0c0 100644 --- a/config_example.toml +++ b/config_example.toml @@ -1,5 +1,4 @@ [global] -timeout = '10s' strategy = 'naive' log_level = 'error' @@ -8,6 +7,7 @@ id = 'ibc-0' rpc_addr = 'tcp://localhost:26657' grpc_addr = 'tcp://localhost:9090' websocket_addr = 'ws://localhost:26657/websocket' +rpc_timeout = '10s' account_prefix = 'cosmos' key_name = 'testkey' store_prefix = 'ibc' @@ -26,6 +26,7 @@ id = 'ibc-1' rpc_addr = 'tcp://localhost:26557' grpc_addr = 'tcp://localhost:9091' websocket_addr = 'ws://localhost:26557/websocket' +rpc_timeout = '10s' account_prefix = 'cosmos' key_name = 'testkey' store_prefix = 'ibc' diff --git a/docs/architecture/adr-002-ibc-relayer.md b/docs/architecture/adr-002-ibc-relayer.md index 487a211fbb..1df200c548 100644 --- a/docs/architecture/adr-002-ibc-relayer.md +++ b/docs/architecture/adr-002-ibc-relayer.md @@ -2,6 +2,7 @@ ## Changelog * 2020-05-19: First draft. Accepted +* 2020-04-06: Configuration updates ## Definitions These definitions are specific for this document and they may not be consistent with the IBC Specification. @@ -110,20 +111,23 @@ The relayer MAY: The initial implementation will heavily borrow from the Go relayer implementation that uses a "naive" algorithm for relaying messages. The structure of the configuration file is similar with the one in Go (see [Go-Relayer](https://github.com/cosmos/relayer)) ### Configuration -(WIP) + +> WIP + Upon start the relayer reads a configuration file that includes global and per chain parameters. The file format is .toml Below is an example of a configuration file. ```toml -title = "IBC Relayer Config Example" - [global] -timeout = "10s" strategy = "naive" +log_level = "error" [[chains]] id = "chain_A" - rpc_addr = "localhost:26657" + rpc_addr = "http://localhost:26657" + grpc_addr = "http://localhost:9090" + websocket_addr = "ws://localhost:26657/websocket" + rpc_timeout = "10s" account_prefix = "cosmos" key_name = "testkey" store_prefix = "ibc" @@ -135,7 +139,10 @@ strategy = "naive" [[chains]] id = "chain_B" - rpc_addr = "localhost:26557" + rpc_addr = "http://localhost:26557" + grpc_addr = "http://localhost:9091" + websocket_addr = "ws://localhost:26557/websocket" + rpc_timeout = "10s" account_prefix = "cosmos" key_name = "testkey" store_prefix = "ibc" @@ -197,13 +204,19 @@ pub enum Strategy { } pub struct GlobalConfig { - pub timeout: Duration, pub strategy: Strategy, + + /// All valid log levels, as defined in tracing: + /// https://docs.rs/tracing-core/0.1.17/tracing_core/struct.Level.html + pub log_level: String, } pub struct ChainConfig { pub id: ChainId, pub rpc_addr: tendermint_rpc::Url, + pub websocket_addr: tendermint_rpc::Url, + pub grpc_addr: tendermint_rpc::Url, + pub rpc_timeout: Duration, pub account_prefix: String, pub key_name: String, pub client_ids: Vec, @@ -248,13 +261,6 @@ To validate a configuration file: The command verifies that the specified configuration file parses and it is semantically correct. -#### Light Client Initialization -To initialize a light client: - -`relayer -c light init -x -h ` - -The command initializes the light client for `` with a trusted height and hash. This should be done for all chains for which relaying is performed. - #### Start To start the relayer: diff --git a/docs/architecture/adr-006-hermes-v0.2-usecases.md b/docs/architecture/adr-006-hermes-v0.2-usecases.md index 4620f33760..ee52cd728e 100644 --- a/docs/architecture/adr-006-hermes-v0.2-usecases.md +++ b/docs/architecture/adr-006-hermes-v0.2-usecases.md @@ -230,7 +230,6 @@ of the config file will look as follows: ```toml [global] -timeout = '10s' strategy = 'naive' log_level = 'error' log_json = 'false' diff --git a/relayer-cli/tests/fixtures/two_chains.toml b/relayer-cli/tests/fixtures/two_chains.toml index d73a2dc06e..0e4548b42a 100644 --- a/relayer-cli/tests/fixtures/two_chains.toml +++ b/relayer-cli/tests/fixtures/two_chains.toml @@ -1,5 +1,4 @@ [global] -timeout = '10s' strategy = 'naive' log_level = 'error' # valid options: 'error', 'warn', 'info', 'debug', 'trace' @@ -8,14 +7,11 @@ id = 'ibc-0' rpc_addr = 'http://127.0.0.1:26657' grpc_addr = 'http://127.0.0.1:9090' websocket_addr = 'ws://127.0.0.1:26657/websocket' +rpc_timeout = '10s' account_prefix = 'cosmos' key_name = 'testkey' store_prefix = 'ibc' - -client_ids = [ - 'cla1', - 'cla2', -] +client_ids = ['cla1', 'cla2'] gas = 200000 clock_drift = '5s' trusting_period = '14days' @@ -24,23 +20,12 @@ trusting_period = '14days' numerator = '1' denominator = '3' -[chains.peers] -primary = 'E0DE6C540C65FC9059660A7A8535F70048A94539' - -[[chains.peers.light_clients]] -peer_id = 'E0DE6C540C65FC9059660A7A8535F70048A94539' -address = 'http://127.0.0.1:26657' -trusted_header_hash = '169F8F6318B8FAABDBA128AD1689E238566B69DDBD2B36F1911C0DFCA73FD401' -trusted_height = '7806' - -[chains.peers.light_clients.store] -type = 'memory' - [[chains]] id = 'ibc-1' rpc_addr = 'http://127.0.0.1:26657' grpc_addr = 'http://127.0.0.1:9090' websocket_addr = 'ws://127.0.0.1:26657/websocket' +rpc_timeout = '10s' account_prefix = 'cosmos' key_name = 'testkey' store_prefix = 'ibc' @@ -52,15 +37,3 @@ trusting_period = '14days' [chains.trust_threshold] numerator = '1' denominator = '3' - -[chains.peers] -primary = '356DB878F398BA707DBE69950067C8E6471D8948' - -[[chains.peers.light_clients]] -peer_id = '356DB878F398BA707DBE69950067C8E6471D8948' -address = 'http://127.0.0.1:26557' -trusted_header_hash = 'CC291E79B2E2068984EB13BBF420B4F4AE95357E25B9BA0A30CA26FF27AF3C75' -trusted_height = '7741' - -[chains.peers.light_clients.store] -type = 'memory' diff --git a/relayer/tests/config/fixtures/relayer_conf_example.toml b/relayer/tests/config/fixtures/relayer_conf_example.toml index 016a8455c3..234c133427 100644 --- a/relayer/tests/config/fixtures/relayer_conf_example.toml +++ b/relayer/tests/config/fixtures/relayer_conf_example.toml @@ -1,5 +1,4 @@ [global] -timeout = '10s' strategy = 'naive' log_level = 'error' @@ -8,6 +7,7 @@ id = 'chain_A' rpc_addr = 'http://127.0.0.1:26657' grpc_addr = 'http://127.0.0.1:9090' websocket_addr = 'ws://localhost:26657/websocket' +rpc_timeout = '10s' account_prefix = 'cosmos' key_name = 'testkey' store_prefix = 'ibc' @@ -28,6 +28,7 @@ id = 'chain_B' rpc_addr = 'http://127.0.0.1:26557' grpc_addr = 'http://127.0.0.1:9090' websocket_addr = 'ws://localhost:26557/websocket' +rpc_timeout = '10s' account_prefix = 'cosmos' key_name = 'testkey' store_prefix = 'ibc' diff --git a/relayer/tests/config/fixtures/simple_config.toml b/relayer/tests/config/fixtures/simple_config.toml index ce62e6d952..bd0bd6a8b2 100644 --- a/relayer/tests/config/fixtures/simple_config.toml +++ b/relayer/tests/config/fixtures/simple_config.toml @@ -3,7 +3,6 @@ title = "IBC Relayer Config Example" [global] -timeout = "10s" strategy = "naive" [[chains]] @@ -11,6 +10,7 @@ strategy = "naive" rpc_addr = "http://127.0.0.1:26657" grpc_addr = 'http://127.0.0.1:9090' websocket_addr = 'ws://localhost:26657/websocket' + rpc_timeout = '10s' account_prefix = "cosmos" key_name = "testkey" store_prefix = "ibc" @@ -21,14 +21,12 @@ strategy = "naive" gas_price = "0.025stake" trusting_period = "336h" - # TODO: Move to light client config - peer_id = "BADFADAD0BEFEEDC0C0ADEADBEEFC0FFEEFACADE" - [[chains]] id = "chain_B" rpc_addr = "http://127.0.0.1:26557" grpc_addr = 'http://127.0.0.1:9090' websocket_addr = 'ws://localhost:26557/websocket' + rpc_timeout = '10s' account_prefix = "cosmos" key_name = "testkey" store_prefix = "ibc" @@ -39,9 +37,6 @@ strategy = "naive" gas_price = "0.025stake" trusting_period = "336h" - # TODO: Move to light client config - peer_id = "DC0C0ADEADBEEFC0FFEEFACADEBADFADAD0BEFEE" - [[connections]] a_chain = "ibc1" b_chain = "ibc0" From 4f94df2cff37260c334db8b7c67afbc744021bbe Mon Sep 17 00:00:00 2001 From: Adi Seredinschi Date: Wed, 7 Apr 2021 16:03:51 +0200 Subject: [PATCH 06/10] Add --locked flag when compiling hermes in init-clients --- scripts/init-clients | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/init-clients b/scripts/init-clients index 27dbcd858f..61411ef19a 100755 --- a/scripts/init-clients +++ b/scripts/init-clients @@ -66,7 +66,7 @@ CHAIN_2_RPC_PORT=26457 CHAIN_2_RPC_ADDR="http://127.0.0.1:$CHAIN_2_RPC_PORT" echo "Building the Rust relayer..." -cargo build -q +cargo build -q --locked # add the key seeds to the keyring of each chain echo "Importing keys..." From ee40c6ea7f6bc57886210e65b90bcc899c92d625 Mon Sep 17 00:00:00 2001 From: Adi Seredinschi Date: Wed, 7 Apr 2021 17:21:38 +0200 Subject: [PATCH 07/10] Fix ibc-proto recompilation bug (#802) * Fixed overwritten cosmos files * changelog * Fix typo in proto-compiler README * Fix bug where proto-compiler didn't find SDK repo if already cloned Co-authored-by: Romain Ruetschi --- CHANGELOG.md | 4 ++ proto-compiler/README.md | 8 ++-- proto-compiler/src/cmd/clone.rs | 40 ++++++++++------- proto-compiler/src/cmd/compile.rs | 73 +++++++++++++++++++++++++------ 4 files changed, 94 insertions(+), 31 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6806059753..4b85b59150 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -56,6 +56,9 @@ - Hermes guide: improved installation guideline ([#672]) - Make fee denom and amount configurable ([#754]) +- [ibc-proto] + - Fix for proto files re-compilation bug ([#801]) + ### BREAKING CHANGES - [ibc] @@ -94,6 +97,7 @@ [#770]: https://github.com/informalsystems/ibc-rs/issues/770 [#793]: https://github.com/informalsystems/ibc-rs/pull/793 [#798]: https://github.com/informalsystems/ibc-rs/issues/798 +[#801]: https://github.com/informalsystems/ibc-rs/issues/801 ## v0.1.1 diff --git a/proto-compiler/README.md b/proto-compiler/README.md index 0ea210c722..967fd3905d 100644 --- a/proto-compiler/README.md +++ b/proto-compiler/README.md @@ -23,7 +23,7 @@ Note: the full commit hash must be specified. Alternatively, one can check out a tag for the Cosmos SDK with the `--sdk-tag` option: ```bash -$ cargo run -- clone --out /tmp/cosmos --sdk-tag v0.42.1 --ibc-commit 333c1f338b2a14a1928a6f8ab64c37123c0e97b6 +$ cargo run -- clone --out /tmp/cosmos --sdk-tag v0.42.1 --ibc-go-commit 333c1f338b2a14a1928a6f8ab64c37123c0e97b6 ``` ### Generate Rust sources from Protobuf definitions @@ -34,6 +34,8 @@ To generate the Rust sources from the Protobuf definitions, and copy them to the $ cargo run -- compile --sdk /tmp/cosmos/sdk --ibc /tmp/cosmos/ibc --out ../proto/src/prost ``` -Additionally, this command will output the commit hash at which the Cosmos SDK is checked out into `$out/COSMOS_SDK_COMMIT`. +Additionally, this command will output the commit hash at which the Cosmos SDK is checked out into `$out/COSMOS_SDK_COMMIT` and +similarly the commit hash for IBC-go is saved into `$out/COSMOS_IBC_VERSION`. -This value is exposed via the `ibc_proto::COSMOS_SDK_VERSION` constant in the `ibc-proto` library. +The two commit values are exposed via the `ibc_proto::COSMOS_SDK_VERSION` and `ibc_proto::COSMOS_IBC_VERSION` +constants in the `ibc-proto` library. diff --git a/proto-compiler/src/cmd/clone.rs b/proto-compiler/src/cmd/clone.rs index 4cfe6e4352..1808a71388 100644 --- a/proto-compiler/src/cmd/clone.rs +++ b/proto-compiler/src/cmd/clone.rs @@ -25,6 +25,9 @@ pub struct CloneCmd { out: PathBuf, } +pub const COSMOS_SDK_URL: &str = "https://github.com/cosmos/cosmos-sdk"; +pub const IBC_GO_URL: &str = "https://github.com/cosmos/ibc-go"; + impl CloneCmd { pub fn validate(&self) { if self.sdk_commit.is_some() && self.sdk_tag.is_some() { @@ -48,27 +51,26 @@ impl CloneCmd { pub fn run(&self) { self.validate(); - let sdk_repo = if self.out.exists() { + let sdk_path = self.sdk_subdir(); + let sdk_repo = if sdk_path.exists() { println!( - "[info ] Found Cosmos SDK or IBC proto source at '{}'", - self.out.display() + "[info ] Found Cosmos SDK source at '{}'", + sdk_path.display() ); - Repository::open(&self.out).unwrap_or_else(|e| { + Repository::open(&sdk_path).unwrap_or_else(|e| { println!("[error] Failed to open repository: {}", e); process::exit(1) }) } else { println!("[info ] Cloning cosmos/cosmos-sdk repository..."); - let url = "https://github.com/cosmos/cosmos-sdk"; - - let repo = Repository::clone(url, &self.sdk_subdir()).unwrap_or_else(|e| { + let repo = Repository::clone(COSMOS_SDK_URL, &sdk_path).unwrap_or_else(|e| { println!("[error] Failed to clone the SDK repository: {}", e); process::exit(1) }); - println!("[info ] Cloned at '{}'", self.sdk_subdir().display()); + println!("[info ] Cloned at '{}'", sdk_path.display()); repo }; @@ -87,17 +89,25 @@ impl CloneCmd { println!("[info ] Cloning cosmos/ibc-go repository..."); - let ibc_url = "https://github.com/cosmos/ibc-go"; + let ibc_path = self.ibc_subdir(); + let ibc_repo = if ibc_path.exists() { + println!("[info ] Found IBC Go source at '{}'", sdk_path.display()); - let ibc_repo = Repository::clone(ibc_url, &self.ibc_subdir()).unwrap_or_else(|e| { - println!("[error] Failed to clone the IBC repository: {}", e); - process::exit(1) - }); + Repository::open(&sdk_path).unwrap_or_else(|e| { + println!("[error] Failed to open repository: {}", e); + process::exit(1) + }) + } else { + Repository::clone(IBC_GO_URL, &ibc_path).unwrap_or_else(|e| { + println!("[error] Failed to clone the IBC Go repository: {}", e); + process::exit(1) + }) + }; - println!("[info ] Cloned at '{}'", self.ibc_subdir().display()); + println!("[info ] Cloned at '{}'", ibc_path.display()); checkout_commit(&ibc_repo, &self.ibc_go_commit).unwrap_or_else(|e| { println!( - "[error] Failed to checkout IBC commit {}: {}", + "[error] Failed to checkout IBC Go commit {}: {}", self.ibc_go_commit, e ); process::exit(1) diff --git a/proto-compiler/src/cmd/compile.rs b/proto-compiler/src/cmd/compile.rs index 733ee8b5ee..92b389f4f4 100644 --- a/proto-compiler/src/cmd/compile.rs +++ b/proto-compiler/src/cmd/compile.rs @@ -27,13 +27,16 @@ pub struct CompileCmd { impl CompileCmd { pub fn run(&self) { - let tmp = TempDir::new("ibc-proto").unwrap(); + let tmp_sdk = TempDir::new("ibc-proto-sdk").unwrap(); + Self::output_version(&self.sdk, tmp_sdk.as_ref(), "COSMOS_SDK_COMMIT"); + Self::compile_sdk_protos(&self.sdk, tmp_sdk.as_ref()); - Self::output_version(&self.sdk, tmp.as_ref(), "COSMOS_SDK_COMMIT"); - Self::output_version(&self.ibc, tmp.as_ref(), "COSMOS_IBC_COMMIT"); - Self::compile_sdk_protos(&self.sdk, tmp.as_ref()); - Self::compile_ibc_protos(&self.ibc, &self.sdk, tmp.as_ref()); - Self::copy_generated_files(tmp.as_ref(), &self.out); + let tmp_ibc = TempDir::new("ibc-proto-ibc-go").unwrap(); + Self::output_version(&self.ibc, tmp_ibc.as_ref(), "COSMOS_IBC_COMMIT"); + Self::compile_ibc_protos(&self.ibc, tmp_ibc.as_ref()); + + // Merge the generated files into a single directory, taking care not to overwrite anything + Self::copy_generated_files(tmp_sdk.as_ref(), tmp_ibc.as_ref(), &self.out); } fn output_version(dir: &Path, out_dir: &Path, commit_file: &str) { @@ -45,7 +48,7 @@ impl CompileCmd { std::fs::write(path, rev).unwrap(); } - fn compile_ibc_protos(ibc_dir: &Path, sdk_dir: &Path, out_dir: &Path) { + fn compile_ibc_protos(ibc_dir: &Path, out_dir: &Path) { println!( "[info ] Compiling IBC .proto files to Rust into '{}'...", out_dir.display() @@ -59,7 +62,6 @@ impl CompileCmd { let proto_includes_paths = [ format!("{}/proto", ibc_dir.display()), - format!("{}/proto/cosmos", sdk_dir.display()), format!("{}/third_party/proto", ibc_dir.display()), ]; @@ -182,7 +184,7 @@ impl CompileCmd { } } - fn copy_generated_files(from_dir: &Path, to_dir: &Path) { + fn copy_generated_files(from_dir_sdk: &Path, from_dir_ibc: &Path, to_dir: &Path) { println!( "[info ] Copying generated files into '{}'...", to_dir.display() @@ -193,7 +195,8 @@ impl CompileCmd { create_dir_all(&to_dir).unwrap(); // Copy new compiled files (prost does not use folder structures) - let errors = WalkDir::new(from_dir) + // Copy the SDK files first + let errors_sdk = WalkDir::new(from_dir_sdk) .into_iter() .filter_map(|e| e.ok()) .filter(|e| e.file_type().is_file()) @@ -210,9 +213,53 @@ impl CompileCmd { .filter_map(|e| e.err()) .collect::>(); - if !errors.is_empty() { - for e in errors { - println!("[error] Error while copying compiled file: {}", e); + if !errors_sdk.is_empty() { + for e in errors_sdk { + println!("[error] Error while copying SDK-compiled file: {}", e); + } + + panic!("[error] Aborted."); + } + + // Copy the IBC-go files second, double-checking if anything is overwritten + let errors_ibc = WalkDir::new(from_dir_ibc) + .into_iter() + .filter_map(|e| e.ok()) + .filter(|e| e.file_type().is_file()) + .map(|e| { + let generated_fname = e.file_name().to_owned().into_string().unwrap(); + let prefix = &generated_fname[0..6]; + + let target_fname = format!( + "{}/{}", + to_dir.display(), + generated_fname, + ); + + // If it's a cosmos-relevant file and it exists, we should not overwrite it. + if Path::new(&target_fname).exists() && prefix.eq("cosmos") { + let original_cosmos_file = std::fs::read(target_fname.clone()).unwrap(); + let new_cosmos_file = std::fs::read(e.path()).unwrap(); + if original_cosmos_file != new_cosmos_file { + println!( + "[warn ] Cosmos-related file exists already {}! Ignoring the one generated from IBC-go {:?}", + target_fname, e.path() + ); + } + Ok(0) + } else { + copy( + e.path(), + target_fname, + ) + } + }) + .filter_map(|e| e.err()) + .collect::>(); + + if !errors_ibc.is_empty() { + for e in errors_ibc { + println!("[error] Error while copying IBC-go compiled file: {}", e); } panic!("[error] Aborted."); From 0d31c26d52fa5de4b3a4c69ace3c8a2a1842dbe7 Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Wed, 7 Apr 2021 17:24:15 +0200 Subject: [PATCH 08/10] Add option to specify which events to listen for in `listen` command (#804) --- CHANGELOG.md | 2 ++ relayer-cli/src/commands/listen.rs | 55 ++++++++++++++++++++++-------- relayer/src/event/monitor.rs | 26 +++++++++++++- 3 files changed, 68 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b85b59150..2ac51f1ed1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ - Added `client-upgrade` CLI ([#357]) - Update gaia to version 4.1.0 for e2e tests on CI ([#702]) - Add `start-multi` command to relay on all paths defined in the configuration ([#748]) + - Add option to specify which events to listen for in `listen` command ([#550]) ### IMPROVEMENTS @@ -75,6 +76,7 @@ [#357]: https://github.com/informalsystems/ibc-rs/issues/357 [#416]: https://github.com/informalsystems/ibc-rs/issues/416 [#561]: https://github.com/informalsystems/ibc-rs/issues/561 +[#550]: https://github.com/informalsystems/ibc-rs/issues/550 [#599]: https://github.com/informalsystems/ibc-rs/issues/599 [#630]: https://github.com/informalsystems/ibc-rs/issues/630 [#672]: https://github.com/informalsystems/ibc-rs/issues/672 diff --git a/relayer-cli/src/commands/listen.rs b/relayer-cli/src/commands/listen.rs index 26070e55db..96400f0e8b 100644 --- a/relayer-cli/src/commands/listen.rs +++ b/relayer-cli/src/commands/listen.rs @@ -2,8 +2,11 @@ use std::{ops::Deref, sync::Arc, thread}; use abscissa_core::{application::fatal_error, error::BoxError, Command, Options, Runnable}; use crossbeam_channel as channel; +use itertools::Itertools; use tokio::runtime::Runtime as TokioRuntime; +use tendermint_rpc::query::{EventType, Query}; + use ibc::ics24_host::identifier::ChainId; use ibc_relayer::{config::ChainConfig, event::monitor::*}; @@ -11,19 +14,30 @@ use crate::prelude::*; #[derive(Command, Debug, Options)] pub struct ListenCmd { + /// Identifier of the chain to listen for events from #[options(free)] - chain_id: Option, + chain_id: ChainId, + + /// Add an event type to listen for, can be repeated. Listen for all events by default (available: Tx, NewBlock) + #[options(short = "e", long = "event", meta = "EVENT")] + events: Vec, } impl ListenCmd { fn cmd(&self) -> Result<(), BoxError> { - let rt = Arc::new(TokioRuntime::new()?); let config = app_config(); - let chain_id = self.chain_id.clone().unwrap(); - let chain_config = config.find_chain(&chain_id).unwrap(); + let chain_config = config + .find_chain(&self.chain_id) + .ok_or_else(|| format!("chain '{}' not found in configuration", self.chain_id))?; + + let events = if self.events.is_empty() { + &[EventType::Tx, EventType::NewBlock] + } else { + self.events.as_slice() + }; - listen(rt, chain_config.clone()) + listen(chain_config, events) } } @@ -35,11 +49,18 @@ impl Runnable for ListenCmd { } /// Listen to events -pub fn listen(rt: Arc, config: ChainConfig) -> Result<(), BoxError> { - info!(chain.id = %config.id, "spawning event monitor for"); +pub fn listen(config: &ChainConfig, events: &[EventType]) -> Result<(), BoxError> { + println!( + "[info] Listening for events `{}` on '{}'...", + events.iter().format(", "), + config.id + ); - let (event_monitor, rx) = subscribe(config, rt)?; - let _ = thread::spawn(|| event_monitor.run()); + let rt = Arc::new(TokioRuntime::new()?); + let queries = events.iter().cloned().map(Query::from).collect(); + let (event_monitor, rx) = subscribe(&config, queries, rt)?; + + thread::spawn(|| event_monitor.run()); while let Ok(event_batch) = rx.recv() { dbg!(event_batch); @@ -49,16 +70,22 @@ pub fn listen(rt: Arc, config: ChainConfig) -> Result<(), BoxError } fn subscribe( - chain_config: ChainConfig, + chain_config: &ChainConfig, + queries: Vec, rt: Arc, ) -> Result<(EventMonitor, channel::Receiver), BoxError> { - let (mut event_monitor, rx) = - EventMonitor::new(chain_config.id, chain_config.websocket_addr, rt) - .map_err(|e| format!("couldn't initialize event monitor: {}", e))?; + let (mut event_monitor, rx) = EventMonitor::new( + chain_config.id.clone(), + chain_config.websocket_addr.clone(), + rt, + ) + .map_err(|e| format!("could not initialize event monitor: {}", e))?; + + event_monitor.set_queries(queries); event_monitor .subscribe() - .map_err(|e| format!("couldn't initialize subscriptions: {}", e))?; + .map_err(|e| format!("could not initialize subscriptions: {}", e))?; Ok((event_monitor, rx)) } diff --git a/relayer/src/event/monitor.rs b/relayer/src/event/monitor.rs index 2f016b749c..1d2286e138 100644 --- a/relayer/src/event/monitor.rs +++ b/relayer/src/event/monitor.rs @@ -32,8 +32,16 @@ impl EventBatch { type SubscriptionResult = Result; type SubscriptionStream = dyn Stream + Send + Sync + Unpin; -/// Connect to a TM node, receive push events over a websocket and filter them for the +/// Connect to a Tendermint node, subscribe to a set of queries, +/// receive push events over a websocket, and filter them for the /// event handler. +/// +/// The default events that are queried are: +/// - [`EventType::NewBlock`] +/// - [`EventType::Tx`] +/// +/// Those can be extending or overriden using +/// [`EventMonitor::add_query`] and [`EventMonitor::set_queries`]. pub struct EventMonitor { chain_id: ChainId, /// WebSocket to collect events from @@ -87,6 +95,22 @@ impl EventMonitor { Ok((monitor, rx)) } + /// Set the queries to subscribe to. + /// + /// ## Note + /// For this change to take effect, one has to [`subscribe`] again. + pub fn set_queries(&mut self, queries: Vec) { + self.event_queries = queries; + } + + /// Add a new query to subscribe to. + /// + /// ## Note + /// For this change to take effect, one has to [`subscribe`] again. + pub fn add_query(&mut self, query: Query) { + self.event_queries.push(query); + } + /// Clear the current subscriptions, and subscribe again to all queries. pub fn subscribe(&mut self) -> Result<(), BoxError> { let mut subscriptions = vec![]; From d0ef290257859af47f72b0b84a10835a1143c945 Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Wed, 7 Apr 2021 17:29:07 +0200 Subject: [PATCH 09/10] Update config_example.toml --- config_example.toml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/config_example.toml b/config_example.toml index 01dfa1e0c0..b335c8a178 100644 --- a/config_example.toml +++ b/config_example.toml @@ -4,8 +4,8 @@ log_level = 'error' [[chains]] id = 'ibc-0' -rpc_addr = 'tcp://localhost:26657' -grpc_addr = 'tcp://localhost:9090' +rpc_addr = 'http://localhost:26657' +grpc_addr = 'http://localhost:9090' websocket_addr = 'ws://localhost:26657/websocket' rpc_timeout = '10s' account_prefix = 'cosmos' @@ -23,8 +23,8 @@ denominator = '3' [[chains]] id = 'ibc-1' -rpc_addr = 'tcp://localhost:26557' -grpc_addr = 'tcp://localhost:9091' +rpc_addr = 'http://localhost:26557' +grpc_addr = 'http://localhost:9091' websocket_addr = 'ws://localhost:26557/websocket' rpc_timeout = '10s' account_prefix = 'cosmos' From a8bb251914094065a991fd2b84f7f1acb07d399c Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Wed, 7 Apr 2021 17:30:03 +0200 Subject: [PATCH 10/10] Rename init-clients to init-hermes --- scripts/dev-env | 2 +- scripts/{init-clients => init-hermes} | 7 ------- 2 files changed, 1 insertion(+), 8 deletions(-) rename scripts/{init-clients => init-hermes} (88%) diff --git a/scripts/dev-env b/scripts/dev-env index 3dfd929573..eeb3dd87ba 100755 --- a/scripts/dev-env +++ b/scripts/dev-env @@ -35,7 +35,7 @@ CHAIN_1_ID="$3" CHAIN_2_ID="$4" SETUP_CHAINS="$(dirname "$0")/setup-chains" -INIT_CLIENTS="$(dirname "$0")/init-clients" +INIT_CLIENTS="$(dirname "$0")/init-hermes" "$SETUP_CHAINS" "$CHAIN_0_ID" "$CHAIN_1_ID" "$CHAIN_2_ID" "$INIT_CLIENTS" "$CONFIG_FILE" "$CHAIN_0_ID" "$CHAIN_1_ID" "$CHAIN_2_ID" diff --git a/scripts/init-clients b/scripts/init-hermes similarity index 88% rename from scripts/init-clients rename to scripts/init-hermes index 61411ef19a..f52ffe8708 100755 --- a/scripts/init-clients +++ b/scripts/init-hermes @@ -58,13 +58,6 @@ fi GAIA_DATA="$(pwd)/data" -CHAIN_0_RPC_PORT=26657 -CHAIN_0_RPC_ADDR="http://127.0.0.1:$CHAIN_0_RPC_PORT" -CHAIN_1_RPC_PORT=26557 -CHAIN_1_RPC_ADDR="http://127.0.0.1:$CHAIN_1_RPC_PORT" -CHAIN_2_RPC_PORT=26457 -CHAIN_2_RPC_ADDR="http://127.0.0.1:$CHAIN_2_RPC_PORT" - echo "Building the Rust relayer..." cargo build -q --locked