diff --git a/.changelog/unreleased/features/3330-disable-verify.md b/.changelog/unreleased/features/3330-disable-verify.md new file mode 100644 index 0000000000..e299176090 --- /dev/null +++ b/.changelog/unreleased/features/3330-disable-verify.md @@ -0,0 +1,15 @@ +- Add a new `trusted_node` setting to the per-chain configuration to + specify whether or not the full node Hermes connects to is trusted. + If not trusted (ie. `trusted_node = false`), Hermes will verify headers + included in the `ClientUpdate` message using the light client. + + If the full node is configured as trusted then, in addition to headers not being verified, + the verification traces will not be provided. + This may cause failure in client updates after significant change in validator sets. + + > **Warning** + > Setting this flag to `true` may reduce latency but at the expense of + > potentially sending invalid client updates to the chain, only use + > when latency is more critical than operating costs. Use at your own risk. + + ([\#3330](https://github.com/informalsystems/hermes/issues/3330)) diff --git a/config.toml b/config.toml index e41c439737..84ed7adc98 100644 --- a/config.toml +++ b/config.toml @@ -132,6 +132,17 @@ websocket_addr = 'ws://127.0.0.1:26657/websocket' # Hermes uses a large preconfigured timeout (on the order of minutes). rpc_timeout = '10s' +# Experimental: Whether or not the full node is trusted. +# +# If not trusted, Hermes will verify headers included in the `ClientUpdate` message using the light client. +# +# Note: If the full node is configured as trusted then, in addition to headers not being verified, +# the verification traces will not be provided. +# This may cause failure in client updates after significant change in validator sets. +# +# Default: false +trusted_node = false + # Delay until event batch is emitted if no NewBlock events have come yet batch_delay = '500ms' @@ -315,6 +326,7 @@ grpc_addr = 'http://127.0.0.1:9091' websocket_addr = 'ws://127.0.0.1:26557/websocket' rpc_timeout = '10s' batch_delay = '500ms' +trusted_node = false account_prefix = 'cosmos' key_name = 'testkey' store_prefix = 'ibc' diff --git a/crates/relayer-cli/Cargo.toml b/crates/relayer-cli/Cargo.toml index 2441cdf03b..669e0d53c7 100644 --- a/crates/relayer-cli/Cargo.toml +++ b/crates/relayer-cli/Cargo.toml @@ -18,7 +18,7 @@ default-run = "hermes" name = "hermes" [features] -default = ["telemetry", "rest-server", "std", "eyre_tracer",] +default = ["telemetry", "rest-server", "std", "eyre_tracer"] std = ["flex-error/std"] eyre_tracer = ["flex-error/eyre_tracer"] profiling = ["ibc-relayer/profiling"] diff --git a/crates/relayer-cli/src/chain_registry.rs b/crates/relayer-cli/src/chain_registry.rs index 36bb2964d8..d23af80cb5 100644 --- a/crates/relayer-cli/src/chain_registry.rs +++ b/crates/relayer-cli/src/chain_registry.rs @@ -122,6 +122,7 @@ where grpc_addr: grpc_address, rpc_timeout: default::rpc_timeout(), batch_delay: default::batch_delay(), + trusted_node: default::trusted_node(), genesis_restart: None, account_prefix: chain_data.bech32_prefix, key_name: String::new(), diff --git a/crates/relayer/src/config.rs b/crates/relayer/src/config.rs index f8a32014b0..78379362fb 100644 --- a/crates/relayer/src/config.rs +++ b/crates/relayer/src/config.rs @@ -185,6 +185,10 @@ pub mod default { Duration::from_secs(30) } + pub fn trusted_node() -> bool { + false + } + pub fn connection_delay() -> Duration { ZERO_DURATION } @@ -459,6 +463,8 @@ pub struct ChainConfig { pub rpc_timeout: Duration, #[serde(default = "default::batch_delay", with = "humantime_serde")] pub batch_delay: Duration, + #[serde(default = "default::trusted_node")] + pub trusted_node: bool, pub account_prefix: String, pub key_name: String, #[serde(default)] diff --git a/crates/relayer/src/light_client/tendermint.rs b/crates/relayer/src/light_client/tendermint.rs index 0fd55533a3..d2f43c9436 100644 --- a/crates/relayer/src/light_client/tendermint.rs +++ b/crates/relayer/src/light_client/tendermint.rs @@ -49,6 +49,7 @@ pub struct LightClient { chain_id: ChainId, peer_id: PeerId, io: AnyIo, + enable_verification: bool, } impl super::LightClient for LightClient { @@ -87,6 +88,15 @@ impl super::LightClient for LightClient { ) -> Result, Error> { trace!(%trusted_height, %target_height, "light client verification"); + if !self.enable_verification { + let target = self.fetch(target_height)?; + + return Ok(Verified { + target, + supporting: vec![], + }); + } + let client = self.prepare_client(client_state, now)?; let mut state = self.prepare_state(trusted_height)?; @@ -279,10 +289,17 @@ impl LightClient { } }; + // If the full node is configured as trusted then, in addition to headers not being verified, + // the verification traces will not be provided. This may cause failure in client + // updates after significant change in validator sets. + let enable_verification = !config.trusted_node; + Ok(Self { chain_id: config.id.clone(), peer_id, io, + + enable_verification, }) } diff --git a/tools/test-framework/src/types/single/node.rs b/tools/test-framework/src/types/single/node.rs index aa730d25ce..a02ea7937c 100644 --- a/tools/test-framework/src/types/single/node.rs +++ b/tools/test-framework/src/types/single/node.rs @@ -142,6 +142,7 @@ impl FullNode { grpc_addr: Url::from_str(&self.chain_driver.grpc_address())?, rpc_timeout: ibc_relayer::config::default::rpc_timeout(), batch_delay: ibc_relayer::config::default::batch_delay(), + trusted_node: false, genesis_restart: None, account_prefix: self.chain_driver.account_prefix.clone(), key_name: self.wallets.relayer.id.0.clone(),