Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CompatMode configuration #3667

Merged
merged 10 commits into from
Nov 2, 2023
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- Add the optional configuration `compat_mode` which can be
used to specify which CometBFT compatibility mode is used.
ljoss17 marked this conversation as resolved.
Show resolved Hide resolved
([\#3623](https://github.com/informalsystems/hermes/issues/3623))
45 changes: 45 additions & 0 deletions .github/workflows/integration.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,51 @@ jobs:
cargo nextest run -p ibc-integration-test --no-fail-fast --failure-output final --test-threads=2 \
--features interchain-security,ics31 interchain_security::

celestia-to-gaia:
runs-on: ubuntu-20.04
strategy:
fail-fast: false
matrix:
chain:
- package: celestia
command: celestia-appd
account_prefix: celestia
native_token: utia
steps:
- uses: actions/checkout@v4
- uses: cachix/install-nix-action@v22
with:
install_url: https://nixos-nix-install-tests.cachix.org/serve/vij683ly7sl95nnhb67bdjjfabclr85m/install
install_options: '--tarball-url-prefix https://nixos-nix-install-tests.cachix.org/serve'
extra_nix_config: |
experimental-features = nix-command flakes
- uses: cachix/cachix-action@v12
with:
name: cosmos
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
override: true
- uses: Swatinem/rust-cache@v2
- uses: actions-rs/cargo@v1
with:
command: test
args: -p ibc-integration-test --features interchain-security --no-fail-fast --no-run
- name: Install cargo-nextest
run: curl -LsSf https://get.nexte.st/latest/linux | tar zxf - -C ${CARGO_HOME:-~/.cargo}/bin
- env:
RUST_LOG: info
RUST_BACKTRACE: 1
NO_COLOR_LOG: 1
COMPAT_MODES: V0_34
CHAIN_COMMAND_PATHS: ${{ matrix.chain.command }},gaiad
ACCOUNT_PREFIXES: ${{ matrix.chain.account_prefix }},cosmos
NATIVE_TOKENS: ${{ matrix.chain.native_token }},stake
run: |
nix shell .#python .#gaia12 .#${{ matrix.chain.package }} -c \
cargo nextest run -p ibc-integration-test --no-fail-fast --failure-output final --test-threads=2 \
--features celestia

model-based-test:
runs-on: ubuntu-20.04
timeout-minutes: 60
Expand Down
9 changes: 9 additions & 0 deletions config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,15 @@ memo_prefix = ''
# submitted to this chain.
# fee_granter = ''

# Specify the CometBFT compatibility mode to use.
# The following behaviours are applied whether the `compat_mode` is configured or not:
# * compat_mode is specified and the version queried from /status is the same as the one configured: Use that version without log output
# * compat_mode is specified but the version queried from /status differs: The CompatMode configured is used, but a warning log is outputted
# * compat_mode is not specified but /status returns a correct version: The CompatMode retrieved from the endpoint is used
# * compat_mode is not specified and /status does not return a valid version: Hermes stops and outputs an error informing the user a compat_mode needs to be configured
# Possible values: [`V0_34`, `V0_37`]
# compat_mode = 'V0_34'
romac marked this conversation as resolved.
Show resolved Hide resolved

[[chains]]
id = 'ibc-1'
rpc_addr = 'http://127.0.0.1:26557'
Expand Down
1 change: 1 addition & 0 deletions crates/relayer-cli/src/chain_registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ where
address_type: AddressType::default(),
sequential_batch_tx: false,
extension_options: Vec::new(),
compat_mode: None,
})
}

Expand Down
7 changes: 3 additions & 4 deletions crates/relayer-cli/src/commands/listen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use ibc_relayer::{
chain::handle::Subscription,
config::{ChainConfig, EventSourceMode},
event::source::EventSource,
util::compat_mode::compat_mode_from_version,
};
use ibc_relayer_types::{core::ics24_host::identifier::ChainId, events::IbcEvent};

Expand Down Expand Up @@ -171,10 +172,8 @@ fn detect_compatibility_mode(
) -> eyre::Result<CompatMode> {
let client = HttpClient::new(config.rpc_addr.clone())?;
let status = rt.block_on(client.status())?;
let compat_mode = CompatMode::from_version(status.node_info.version).unwrap_or_else(|e| {
warn!("Unsupported tendermint version, will use v0.34 compatibility mode but relaying might not work as desired: {e}");
CompatMode::V0_34
});
let compat_mode =
compat_mode_from_version(&config.compat_mode, status.node_info.version)?.into();
Ok(compat_mode)
}

Expand Down
6 changes: 2 additions & 4 deletions crates/relayer/src/chain/cosmos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ use crate::keyring::{KeyRing, Secp256k1KeyPair, SigningKeyPair};
use crate::light_client::tendermint::LightClient as TmLightClient;
use crate::light_client::{LightClient, Verified};
use crate::misbehaviour::MisbehaviourEvidence;
use crate::util::compat_mode::compat_mode_from_version;
use crate::util::pretty::{
PrettyIdentifiedChannel, PrettyIdentifiedClientState, PrettyIdentifiedConnection,
};
Expand Down Expand Up @@ -875,10 +876,7 @@ impl ChainEndpoint for CosmosSdkChain {

let node_info = rt.block_on(fetch_node_info(&rpc_client, &config))?;

let compat_mode = CompatMode::from_version(node_info.version).unwrap_or_else(|e| {
warn!("Unsupported tendermint version, will use v0.34 compatibility mode but relaying might not work as desired: {e}");
CompatMode::V0_34
});
let compat_mode = compat_mode_from_version(&config.compat_mode, node_info.version)?.into();
rpc_client.set_compat_mode(compat_mode);

let light_client = TmLightClient::from_config(&config, node_info.id)?;
Expand Down
61 changes: 60 additions & 1 deletion crates/relayer/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ use std::{
};
use tendermint::block::Height as BlockHeight;
use tendermint_light_client::verifier::types::TrustThreshold;
use tendermint_rpc::{Url, WebSocketClientUrl};
use tendermint_rpc::client::CompatMode as TmCompatMode;
use tendermint_rpc::Url;
use tendermint_rpc::WebSocketClientUrl;

use ibc_proto::google::protobuf::Any;
use ibc_relayer_types::core::ics23_commitment::specs::ProofSpecs;
Expand Down Expand Up @@ -146,6 +148,62 @@ impl Display for ExtensionOption {
}
}

#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
ljoss17 marked this conversation as resolved.
Show resolved Hide resolved
pub enum CompatMode {
/// Use version 0.34 of the protocol.
V0_34,
/// Use version 0.37 of the protocol.
V0_37,
}

impl Display for CompatMode {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
match self {
Self::V0_34 => write!(f, "v0.34"),
Self::V0_37 => write!(f, "v0.37"),
}
}
}

impl FromStr for CompatMode {
type Err = Error;

fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"V0_34" => Ok(Self::V0_34),
"V0_37" => Ok(Self::V0_37),
_ => Err(Error::invalid_compat_mode(s.to_owned())),
}
romac marked this conversation as resolved.
Show resolved Hide resolved
}
}

impl From<TmCompatMode> for CompatMode {
fn from(value: TmCompatMode) -> Self {
match value {
TmCompatMode::V0_34 => Self::V0_34,
TmCompatMode::V0_37 => Self::V0_37,
}
}
}

impl From<CompatMode> for TmCompatMode {
fn from(value: CompatMode) -> Self {
match value {
CompatMode::V0_34 => Self::V0_34,
CompatMode::V0_37 => Self::V0_37,
}
}
}

impl CompatMode {
pub fn equal_to_tm_compat_mode(&self, tm_compat_mode: TmCompatMode) -> bool {
match self {
Self::V0_34 => tm_compat_mode == TmCompatMode::V0_34,
Self::V0_37 => tm_compat_mode == TmCompatMode::V0_37,
}
}
}

/// Defaults for various fields
pub mod default {
use super::*;
Expand Down Expand Up @@ -663,6 +721,7 @@ pub struct ChainConfig {
pub address_type: AddressType,
#[serde(default = "Vec::new", skip_serializing_if = "Vec::is_empty")]
pub extension_options: Vec<ExtensionOption>,
pub compat_mode: Option<CompatMode>,
}

/// Attempt to load and parse the TOML config file as a `Config`.
Expand Down
4 changes: 4 additions & 0 deletions crates/relayer/src/config/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ define_error! {
[ TraceError<toml::de::Error> ]
|_| { "invalid configuration" },

InvalidCompatMode
{ compat_mode: String }
|e| { format!("invalid compat mode: {}", e.compat_mode) },

Encode
[ TraceError<toml::ser::Error> ]
|_| { "invalid configuration" },
Expand Down
4 changes: 4 additions & 0 deletions crates/relayer/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -591,6 +591,10 @@ define_error! {
{ address: String }
[ TendermintRpcError ]
|e| { format!("invalid archive node address {}", e.address) },

InvalidCompatMode
[ TendermintRpcError ]
|_| { "Invalid CompatMode queried from chain and no `compat_mode` configured in Hermes. This can be fixed by specifying a `compat_mode` in Hermes config.toml" },
}
}

Expand Down
1 change: 1 addition & 0 deletions crates/relayer/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ mod block_on;
pub use block_on::{block_on, spawn_blocking};

pub mod collate;
pub mod compat_mode;
pub mod debug_section;
pub mod diff;
pub mod iter;
Expand Down
27 changes: 27 additions & 0 deletions crates/relayer/src/util/compat_mode.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
use tracing::warn;

use tendermint::Version;
use tendermint_rpc::client::CompatMode as TmCompatMode;

use crate::config::CompatMode;
use crate::error::Error;

/// This is a wrapper around tendermint-rs CompatMode::from_version() method.
///
pub fn compat_mode_from_version(
configured_version: &Option<CompatMode>,
version: Version,
) -> Result<CompatMode, Error> {
let queried_version = TmCompatMode::from_version(version);

// This will prioritize the use of the CompatMode specified in Hermes configuration file
match (configured_version, queried_version) {
(Some(configured), Ok(queried)) if !configured.equal_to_tm_compat_mode(queried) => {
warn!("Be wary of potential CompatMode version misconfiguration. Configured version: {}, Version output from chain: {}. Hermes will use the configured CompatMode version `{}`. If this configuration is done on purpose this message can be ignored.", configured, queried, configured);
ljoss17 marked this conversation as resolved.
Show resolved Hide resolved
Ok(configured.clone())
}
(Some(configured), _) => Ok(configured.clone()),
(_, Ok(queried)) => Ok(queried.into()),
(_, Err(e)) => Err(Error::invalid_compat_mode(e)),
}
}
Loading
Loading