diff --git a/.changelog/unreleased/features/ibc-relayer/4040-disable-ics31-icqs.md b/.changelog/unreleased/features/ibc-relayer/4040-disable-ics31-icqs.md new file mode 100644 index 0000000000..98ea3ddc6d --- /dev/null +++ b/.changelog/unreleased/features/ibc-relayer/4040-disable-ics31-icqs.md @@ -0,0 +1,3 @@ +- Add a new per-chain configuration `allow_ccq` to enable or disable + relaying of ICS31 Cross Chain Query packets. + ([\#4040](https://github.com/informalsystems/hermes/issues/4040)) \ No newline at end of file diff --git a/config.toml b/config.toml index b7542579ca..ca679a9b3f 100644 --- a/config.toml +++ b/config.toml @@ -453,6 +453,13 @@ memo_prefix = '' # Default: No filter # excluded_sequences = {} +# Enable or disable relaying of ICS31 Cross Chain Query packets. +# If this configuration is set to false, Hermes will skip ICS31 +# Cross Chain Query packets. +# +# Default: true +# allow_ccq = true + [[chains]] id = 'ibc-1' rpc_addr = 'http://127.0.0.1:26557' diff --git a/crates/relayer-cli/src/chain_registry.rs b/crates/relayer-cli/src/chain_registry.rs index c52e6190db..f9fdb22d1d 100644 --- a/crates/relayer-cli/src/chain_registry.rs +++ b/crates/relayer-cli/src/chain_registry.rs @@ -169,6 +169,7 @@ where compat_mode: None, clear_interval: None, excluded_sequences: ExcludedSequences::new(BTreeMap::new()), + allow_ccq: true, })) } diff --git a/crates/relayer/src/chain/cosmos/config.rs b/crates/relayer/src/chain/cosmos/config.rs index 3993c653b9..911e147f32 100644 --- a/crates/relayer/src/chain/cosmos/config.rs +++ b/crates/relayer/src/chain/cosmos/config.rs @@ -149,6 +149,9 @@ pub struct CosmosSdkConfig { pub clear_interval: Option, #[serde(default)] pub excluded_sequences: ExcludedSequences, + + #[serde(default = "default::allow_ccq")] + pub allow_ccq: bool, } impl CosmosSdkConfig { diff --git a/crates/relayer/src/config.rs b/crates/relayer/src/config.rs index 066bd93a97..80e4923aa1 100644 --- a/crates/relayer/src/config.rs +++ b/crates/relayer/src/config.rs @@ -246,6 +246,10 @@ pub mod default { pub fn ics20_max_receiver_size() -> Ics20FieldSizeLimit { Ics20FieldSizeLimit::new(true, Byte::from_bytes(2048)) } + + pub fn allow_ccq() -> bool { + true + } } #[derive(Clone, Debug, Default, Deserialize, Serialize)] @@ -725,6 +729,12 @@ impl ChainConfig { .unwrap_or_else(|| Cow::Owned(Vec::new())), } } + + pub fn allow_ccq(&self) -> bool { + match self { + Self::CosmosSdk(config) => config.allow_ccq, + } + } } // /!\ Update me when adding a new chain type! diff --git a/crates/relayer/src/worker.rs b/crates/relayer/src/worker.rs index 4315c05581..2705919e6d 100644 --- a/crates/relayer/src/worker.rs +++ b/crates/relayer/src/worker.rs @@ -209,16 +209,24 @@ pub fn spawn_worker_tasks( } Object::CrossChainQuery(cross_chain_query) => { - let (cmd_tx, cmd_rx) = crossbeam_channel::unbounded(); - let cross_chain_query_task = cross_chain_query::spawn_cross_chain_query_worker( - chains.a.clone(), - chains.b, - cmd_rx, - cross_chain_query.clone(), - ); - task_handles.push(cross_chain_query_task); - - (Some(cmd_tx), None) + if config + .chains + .iter() + .any(|chain| chain.id() == &cross_chain_query.dst_chain_id && chain.allow_ccq()) + { + let (cmd_tx, cmd_rx) = crossbeam_channel::unbounded(); + let cross_chain_query_task = cross_chain_query::spawn_cross_chain_query_worker( + chains.a.clone(), + chains.b, + cmd_rx, + cross_chain_query.clone(), + ); + task_handles.push(cross_chain_query_task); + + (Some(cmd_tx), None) + } else { + (None, None) + } } }; diff --git a/tools/integration-test/src/tests/interchain_security/icq.rs b/tools/integration-test/src/tests/interchain_security/icq.rs index 3c78fbac3e..19f2a84efb 100644 --- a/tools/integration-test/src/tests/interchain_security/icq.rs +++ b/tools/integration-test/src/tests/interchain_security/icq.rs @@ -9,6 +9,7 @@ //! The test then waits for a Cross-chain Query to be pending and //! then processed. +use ibc_relayer::config::ChainConfig; use ibc_test_framework::chain::cli::host_zone::register_host_zone; use ibc_test_framework::chain::config::{ set_crisis_denom, set_mint_mint_denom, set_staking_bond_denom, set_staking_max_entries, @@ -27,10 +28,17 @@ use ibc_test_framework::util::random::random_u128_range; #[test] fn test_ics31_cross_chain_queries() -> Result<(), Error> { - run_binary_interchain_security_channel_test(&InterchainSecurityIcqTest) + run_binary_interchain_security_channel_test(&InterchainSecurityIcqTest { allow_ccq: true }) } -struct InterchainSecurityIcqTest; +#[test] +fn test_disable_ics31_cross_chain_queries() -> Result<(), Error> { + run_binary_interchain_security_channel_test(&InterchainSecurityIcqTest { allow_ccq: false }) +} + +struct InterchainSecurityIcqTest { + pub allow_ccq: bool, +} impl TestOverrides for InterchainSecurityIcqTest { fn modify_genesis_file(&self, genesis: &mut serde_json::Value) -> Result<(), Error> { @@ -81,6 +89,14 @@ impl TestOverrides for InterchainSecurityIcqTest { config.mode.channels.enabled = true; update_relayer_config_for_consumer_chain(config); + + for chain in config.chains.iter_mut() { + match chain { + ChainConfig::CosmosSdk(chain_config) => { + chain_config.allow_ccq = self.allow_ccq; + } + } + } } } @@ -175,10 +191,17 @@ impl BinaryChannelTest for InterchainSecurityIcqTest { .assert_pending_cross_chain_query()?; // After there is a pending cross chain query, wait for it to be processed - chains + let processed_ccqs = chains .node_b .chain_driver() - .assert_processed_cross_chain_query()?; + .assert_processed_cross_chain_query(); + + if self.allow_ccq { + assert!(processed_ccqs.is_ok()); + } else { + assert!(processed_ccqs.is_err()); + } + Ok(()) } } diff --git a/tools/test-framework/src/chain/ext/crosschainquery.rs b/tools/test-framework/src/chain/ext/crosschainquery.rs index aca80110b8..f41f89abeb 100644 --- a/tools/test-framework/src/chain/ext/crosschainquery.rs +++ b/tools/test-framework/src/chain/ext/crosschainquery.rs @@ -14,7 +14,7 @@ use crate::types::tagged::MonoTagged; If you encounter retry error, verify the value of `stride_epoch`in the `stride_epoch` configuration in Stride's `genesis.toml` file. */ -const WAIT_CROSS_CHAIN_QUERY_ATTEMPTS: u16 = 100; +const WAIT_CROSS_CHAIN_QUERY_ATTEMPTS: u16 = 30; pub trait CrossChainQueryMethodsExt { fn assert_pending_cross_chain_query(&self) -> Result<(), Error>; diff --git a/tools/test-framework/src/types/single/node.rs b/tools/test-framework/src/types/single/node.rs index 145b0a74f9..fd19ebbd3f 100644 --- a/tools/test-framework/src/types/single/node.rs +++ b/tools/test-framework/src/types/single/node.rs @@ -200,6 +200,7 @@ impl FullNode { compat_mode, clear_interval: None, excluded_sequences: ExcludedSequences::new(BTreeMap::new()), + allow_ccq: true, })) }