From 6364535350fba913c9c9b1b17cf7a5f7e76c11f8 Mon Sep 17 00:00:00 2001 From: Luca Joss Date: Fri, 7 Jun 2024 09:36:17 +0200 Subject: [PATCH 1/6] Add a filter at supervisor level for CCQ to verify if the destination chain is configured --- crates/relayer/src/object.rs | 12 ++++++++++++ crates/relayer/src/supervisor.rs | 4 +++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/crates/relayer/src/object.rs b/crates/relayer/src/object.rs index aac3efb257..007bfa4841 100644 --- a/crates/relayer/src/object.rs +++ b/crates/relayer/src/object.rs @@ -21,7 +21,9 @@ use crate::chain::{ handle::ChainHandle, requests::{IncludeProof, QueryClientStateRequest, QueryHeight}, }; +use crate::config::ChainConfig; use crate::error::Error as RelayerError; +use crate::supervisor::client_state_filter::Permission; use crate::supervisor::Error as SupervisorError; /// Client @@ -145,6 +147,16 @@ impl CrossChainQuery { pub fn short_name(&self) -> String { format!("cross_chain_query::{}/{}", self.dst_chain_id, self.query_id) } + + pub fn check_validity(&self, chain_configs: &[ChainConfig]) -> Permission { + if chain_configs + .iter() + .any(|config| *config.id() == self.dst_chain_id) + { + return Permission::Allow; + } + Permission::Deny + } } /// An object determines the amount of parallelism that can diff --git a/crates/relayer/src/supervisor.rs b/crates/relayer/src/supervisor.rs index 16ca340703..4a23075a33 100644 --- a/crates/relayer/src/supervisor.rs +++ b/crates/relayer/src/supervisor.rs @@ -374,13 +374,15 @@ fn relay_on_object( }; // Then, apply the client filter + // If the object is a CrossChain query discard it if the destination chain + // is not configured let client_filter_outcome = match object { Object::Client(client) => client_state_filter.control_client_object(registry, client), Object::Connection(conn) => client_state_filter.control_conn_object(registry, conn), Object::Channel(chan) => client_state_filter.control_chan_object(registry, chan), Object::Packet(packet) => client_state_filter.control_packet_object(registry, packet), Object::Wallet(_wallet) => Ok(Permission::Allow), - Object::CrossChainQuery(_) => Ok(Permission::Allow), + Object::CrossChainQuery(ccq) => Ok(ccq.check_validity(&config.chains)), }; match client_filter_outcome { From 0e0965d5fad3c642c322edb95496edea000b1df4 Mon Sep 17 00:00:00 2001 From: Luca Joss Date: Fri, 7 Jun 2024 09:36:37 +0200 Subject: [PATCH 2/6] Update all MSRVs to v1.76.0 --- crates/chain-registry/Cargo.toml | 2 +- crates/relayer-rest/Cargo.toml | 2 +- crates/relayer-rest/README.md | 4 ++-- crates/relayer-types/Cargo.toml | 2 +- crates/relayer/Cargo.toml | 2 +- crates/telemetry/Cargo.toml | 2 +- tools/integration-test/Cargo.toml | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/crates/chain-registry/Cargo.toml b/crates/chain-registry/Cargo.toml index c2b79fb856..3b67a54933 100644 --- a/crates/chain-registry/Cargo.toml +++ b/crates/chain-registry/Cargo.toml @@ -6,7 +6,7 @@ license = "Apache-2.0" keywords = ["cosmos", "ibc", "relayer", "chain", "registry"] repository = "https://github.com/informalsystems/hermes" authors = ["Informal Systems "] -rust-version = "1.71.1" +rust-version = "1.76.0" description = """ Service to fetch data from the chain-registry """ diff --git a/crates/relayer-rest/Cargo.toml b/crates/relayer-rest/Cargo.toml index d831f4bda8..3a5a87630e 100644 --- a/crates/relayer-rest/Cargo.toml +++ b/crates/relayer-rest/Cargo.toml @@ -8,7 +8,7 @@ readme = "README.md" keywords = ["ibc", "rest", "api", "cosmos", "tendermint"] homepage = "https://hermes.informal.systems/" repository = "https://github.com/informalsystems/hermes" -rust-version = "1.71.1" +rust-version = "1.76.0" description = """ Rust implementation of a RESTful API server for Hermes """ diff --git a/crates/relayer-rest/README.md b/crates/relayer-rest/README.md index 82f3e7fd78..db2dd9ca9f 100644 --- a/crates/relayer-rest/README.md +++ b/crates/relayer-rest/README.md @@ -6,7 +6,7 @@ [![End to End testing][e2e-image]][e2e-link] [![Apache 2.0 Licensed][license-image]][license-link] ![Rust Stable][rustc-image] -![Rust 1.71.1+][rustc-version] +![Rust 1.76.0+][rustc-version] This is the repository for the IBC REST server for use in the Hermes IBC relayer. @@ -39,4 +39,4 @@ Unless required by applicable law or agreed to in writing, software distributed [license-image]: https://img.shields.io/badge/license-Apache2.0-blue.svg [license-link]: https://github.com/informalsystems/hermes/blob/master/LICENSE [rustc-image]: https://img.shields.io/badge/rustc-stable-blue.svg -[rustc-version]: https://img.shields.io/badge/rustc-1.71.1+-blue.svg +[rustc-version]: https://img.shields.io/badge/rustc-1.76.0+-blue.svg diff --git a/crates/relayer-types/Cargo.toml b/crates/relayer-types/Cargo.toml index 578d924eaf..1fb982d1b9 100644 --- a/crates/relayer-types/Cargo.toml +++ b/crates/relayer-types/Cargo.toml @@ -7,7 +7,7 @@ readme = "README.md" keywords = ["blockchain", "consensus", "cosmos", "ibc", "tendermint"] repository = "https://github.com/informalsystems/hermes" authors = ["Informal Systems "] -rust-version = "1.71.1" +rust-version = "1.76.0" description = """ Implementation of the Inter-Blockchain Communication Protocol (IBC). This crate comprises the main data structures and on-chain logic. diff --git a/crates/relayer/Cargo.toml b/crates/relayer/Cargo.toml index 7691ca00ea..4404510d12 100644 --- a/crates/relayer/Cargo.toml +++ b/crates/relayer/Cargo.toml @@ -7,7 +7,7 @@ readme = "README.md" keywords = ["blockchain", "consensus", "cosmos", "ibc", "tendermint"] repository = "https://github.com/informalsystems/hermes" authors = ["Informal Systems "] -rust-version = "1.71.1" +rust-version = "1.76.0" description = """ Implementation of an IBC Relayer in Rust, as a library """ diff --git a/crates/telemetry/Cargo.toml b/crates/telemetry/Cargo.toml index fa5e6ef05c..10454d2f25 100644 --- a/crates/telemetry/Cargo.toml +++ b/crates/telemetry/Cargo.toml @@ -7,7 +7,7 @@ readme = "README.md" keywords = ["cosmos", "ibc", "relayer", "telemetry"] repository = "https://github.com/informalsystems/hermes" authors = ["Informal Systems "] -rust-version = "1.71.1" +rust-version = "1.76.0" description = """ Telemetry service for the Hermes IBC relayer """ diff --git a/tools/integration-test/Cargo.toml b/tools/integration-test/Cargo.toml index 8a0a8dacf7..3e96b65be3 100644 --- a/tools/integration-test/Cargo.toml +++ b/tools/integration-test/Cargo.toml @@ -2,7 +2,7 @@ name = "ibc-integration-test" version = "0.28.0" edition = "2021" -rust-version = "1.71.1" +rust-version = "1.76.0" license = "Apache-2.0" readme = "README.md" keywords = ["blockchain", "consensus", "cosmos", "ibc", "tendermint"] From f9f4a8865fa5df05349416234c5860742626abb4 Mon Sep 17 00:00:00 2001 From: Luca Joss Date: Fri, 7 Jun 2024 09:44:02 +0200 Subject: [PATCH 3/6] Add changelog entry --- .../features/ibc-relayer/4021-chain-level-ccq-filter.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .changelog/unreleased/features/ibc-relayer/4021-chain-level-ccq-filter.md diff --git a/.changelog/unreleased/features/ibc-relayer/4021-chain-level-ccq-filter.md b/.changelog/unreleased/features/ibc-relayer/4021-chain-level-ccq-filter.md new file mode 100644 index 0000000000..d3b2c7f51f --- /dev/null +++ b/.changelog/unreleased/features/ibc-relayer/4021-chain-level-ccq-filter.md @@ -0,0 +1,2 @@ +- Discard CrossChain queries intended for unconfigured chains. + ([\#4021](https://github.com/informalsystems/hermes/issues/4021)) \ No newline at end of file From 926ce1b38f31e0a6ef37d5dfc3475b317003a596 Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Fri, 7 Jun 2024 10:44:25 +0200 Subject: [PATCH 4/6] Renaming --- crates/relayer/src/object.rs | 7 ++++--- crates/relayer/src/supervisor.rs | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/crates/relayer/src/object.rs b/crates/relayer/src/object.rs index 007bfa4841..4716a5d5cf 100644 --- a/crates/relayer/src/object.rs +++ b/crates/relayer/src/object.rs @@ -148,14 +148,15 @@ impl CrossChainQuery { format!("cross_chain_query::{}/{}", self.dst_chain_id, self.query_id) } - pub fn check_validity(&self, chain_configs: &[ChainConfig]) -> Permission { + pub fn intended_for_known_dst_chain(&self, chain_configs: &[ChainConfig]) -> Permission { if chain_configs .iter() .any(|config| *config.id() == self.dst_chain_id) { - return Permission::Allow; + Permission::Allow + } else { + Permission::Deny } - Permission::Deny } } diff --git a/crates/relayer/src/supervisor.rs b/crates/relayer/src/supervisor.rs index 4a23075a33..9a5b0f17a3 100644 --- a/crates/relayer/src/supervisor.rs +++ b/crates/relayer/src/supervisor.rs @@ -381,8 +381,8 @@ fn relay_on_object( Object::Connection(conn) => client_state_filter.control_conn_object(registry, conn), Object::Channel(chan) => client_state_filter.control_chan_object(registry, chan), Object::Packet(packet) => client_state_filter.control_packet_object(registry, packet), + Object::CrossChainQuery(ccq) => Ok(ccq.intended_for_known_dst_chain(&config.chains)), Object::Wallet(_wallet) => Ok(Permission::Allow), - Object::CrossChainQuery(ccq) => Ok(ccq.check_validity(&config.chains)), }; match client_filter_outcome { From e3ef2378330b336fa61c97446cf86214f0f782f3 Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Fri, 7 Jun 2024 10:45:41 +0200 Subject: [PATCH 5/6] Move changelog entry under bug fixes --- .../ibc-relayer/4021-chain-level-ccq-filter.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .changelog/unreleased/{features => bug-fixes}/ibc-relayer/4021-chain-level-ccq-filter.md (100%) diff --git a/.changelog/unreleased/features/ibc-relayer/4021-chain-level-ccq-filter.md b/.changelog/unreleased/bug-fixes/ibc-relayer/4021-chain-level-ccq-filter.md similarity index 100% rename from .changelog/unreleased/features/ibc-relayer/4021-chain-level-ccq-filter.md rename to .changelog/unreleased/bug-fixes/ibc-relayer/4021-chain-level-ccq-filter.md From 6592625d923f785ea5cd2e3daa8c234a6ef1dbf4 Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Mon, 10 Jun 2024 15:50:05 +0200 Subject: [PATCH 6/6] Ensure we process all events in a batch, even when some of them are rejected by the filtering policy --- .../4034-ensure-no-dropped-events.md | 3 ++ crates/relayer/src/object.rs | 13 ----- crates/relayer/src/supervisor.rs | 54 ++++++++++++------- 3 files changed, 38 insertions(+), 32 deletions(-) create mode 100644 .changelog/unreleased/bug-fixes/4034-ensure-no-dropped-events.md diff --git a/.changelog/unreleased/bug-fixes/4034-ensure-no-dropped-events.md b/.changelog/unreleased/bug-fixes/4034-ensure-no-dropped-events.md new file mode 100644 index 0000000000..d0943e5245 --- /dev/null +++ b/.changelog/unreleased/bug-fixes/4034-ensure-no-dropped-events.md @@ -0,0 +1,3 @@ +- Fix a bug where in some cases, Hermes would drop all events in a + batch that came after an event rejected by the filtering policy + ([\#4034](https://github.com/informalsystems/hermes/issues/4034)) \ No newline at end of file diff --git a/crates/relayer/src/object.rs b/crates/relayer/src/object.rs index 4716a5d5cf..aac3efb257 100644 --- a/crates/relayer/src/object.rs +++ b/crates/relayer/src/object.rs @@ -21,9 +21,7 @@ use crate::chain::{ handle::ChainHandle, requests::{IncludeProof, QueryClientStateRequest, QueryHeight}, }; -use crate::config::ChainConfig; use crate::error::Error as RelayerError; -use crate::supervisor::client_state_filter::Permission; use crate::supervisor::Error as SupervisorError; /// Client @@ -147,17 +145,6 @@ impl CrossChainQuery { pub fn short_name(&self) -> String { format!("cross_chain_query::{}/{}", self.dst_chain_id, self.query_id) } - - pub fn intended_for_known_dst_chain(&self, chain_configs: &[ChainConfig]) -> Permission { - if chain_configs - .iter() - .any(|config| *config.id() == self.dst_chain_id) - { - Permission::Allow - } else { - Permission::Deny - } - } } /// An object determines the amount of parallelism that can diff --git a/crates/relayer/src/supervisor.rs b/crates/relayer/src/supervisor.rs index 9a5b0f17a3..c994ac6585 100644 --- a/crates/relayer/src/supervisor.rs +++ b/crates/relayer/src/supervisor.rs @@ -381,7 +381,7 @@ fn relay_on_object( Object::Connection(conn) => client_state_filter.control_conn_object(registry, conn), Object::Channel(chan) => client_state_filter.control_chan_object(registry, chan), Object::Packet(packet) => client_state_filter.control_packet_object(registry, packet), - Object::CrossChainQuery(ccq) => Ok(ccq.intended_for_known_dst_chain(&config.chains)), + Object::CrossChainQuery(_ccq) => Ok(Permission::Allow), Object::Wallet(_wallet) => Ok(Permission::Allow), }; @@ -816,8 +816,33 @@ fn process_batch( workers.notify_new_block(&src_chain.id(), batch.height, new_block); } - // Forward the IBC events. + // Forward the IBC events to the appropriate workers for (object, events_with_heights) in collected.per_object.into_iter() { + if events_with_heights.is_empty() { + // Event batch is empty, nothing to do + continue; + } + + let Ok(src_chain) = registry.get_or_spawn(object.src_chain_id()) else { + trace!( + "skipping events for '{}': source chain '{}' is not registered", + object.short_name(), + object.src_chain_id() + ); + + continue; + }; + + let Ok(dst_chain) = registry.get_or_spawn(object.dst_chain_id()) else { + trace!( + "skipping events for '{}': destination chain '{}' is not registered", + object.short_name(), + object.src_chain_id() + ); + + continue; + }; + if !relay_on_object( config, registry, @@ -826,32 +851,23 @@ fn process_batch( &object, ) { trace!( - "skipping events for '{}'. \ - reason: filtering is enabled and channel does not match any allowed channels", + "skipping events for '{}': rejected by filtering policy", object.short_name() ); continue; } - if events_with_heights.is_empty() { - continue; - } - - let src = registry - .get_or_spawn(object.src_chain_id()) - .map_err(Error::spawn)?; - - let dst = registry - .get_or_spawn(object.dst_chain_id()) - .map_err(Error::spawn)?; - if let Object::Packet(ref _path) = object { - // Update telemetry info - telemetry!(send_telemetry(&src, &dst, &events_with_heights, _path)); + telemetry!(send_telemetry( + &src_chain, + &dst_chain, + &events_with_heights, + _path + )); } - let worker = workers.get_or_spawn(object, src, dst, config); + let worker = workers.get_or_spawn(object, src_chain, dst_chain, config); worker.send_events( batch.height,