diff --git a/Cargo.lock b/Cargo.lock index adca6e2e9c..7bb0fd276b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1425,6 +1425,7 @@ dependencies = [ "ibc-telemetry", "itertools 0.10.5", "moka", + "monostate", "num-bigint", "num-rational", "once_cell", @@ -1887,6 +1888,27 @@ dependencies = [ "uuid 1.6.1", ] +[[package]] +name = "monostate" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "878c2a1f1c70e5724fa28f101ca787b6a7e8ad5c5e4ae4ca3b0fa4a419fa9075" +dependencies = [ + "monostate-impl", + "serde", +] + +[[package]] +name = "monostate-impl" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f686d68a09079e63b1d2c64aa305095887ce50565f00a922ebfaeeee0d9ba6ce" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "nu-ansi-term" version = "0.46.0" diff --git a/config.toml b/config.toml index 9ff0aa5ed3..06dabdac13 100644 --- a/config.toml +++ b/config.toml @@ -154,7 +154,8 @@ port = 5555 # Specify the chain ID. Required id = 'ibc-0' -# Specify the chain type, currently only `"CosmosSdk"` is supported. +# Specify the chain type, currently only `CosmosSdk` is supported. +# Default: CosmosSdk type = "CosmosSdk" # Whether or not this is a CCV consumer chain. Default: false @@ -422,7 +423,6 @@ memo_prefix = '' [[chains]] id = 'ibc-1' -type = "CosmosSdk" rpc_addr = 'http://127.0.0.1:26557' grpc_addr = 'http://127.0.0.1:9091' event_source = { mode = 'push', url = 'ws://127.0.0.1:26557/websocket', batch_delay = '500ms' } diff --git a/crates/relayer-cli/src/chain_registry.rs b/crates/relayer-cli/src/chain_registry.rs index df63a513c1..520a58a011 100644 --- a/crates/relayer-cli/src/chain_registry.rs +++ b/crates/relayer-cli/src/chain_registry.rs @@ -121,6 +121,7 @@ where }; Ok(ChainConfig::CosmosSdk(CosmosSdkConfig { + r#type: Default::default(), id: chain_data.chain_id, rpc_addr: rpc_data.rpc_address, grpc_addr: grpc_address, diff --git a/crates/relayer/Cargo.toml b/crates/relayer/Cargo.toml index 1a6db3787f..c60227263b 100644 --- a/crates/relayer/Cargo.toml +++ b/crates/relayer/Cargo.toml @@ -70,6 +70,7 @@ strum = { version = "0.25", features = ["derive"] } tokio-stream = "0.1.14" once_cell = "1.19.0" tracing-subscriber = { version = "0.3.14", features = ["fmt", "env-filter", "json"] } +monostate = "0.1.11" [dependencies.byte-unit] version = "4.0.19" diff --git a/crates/relayer/src/chain/cosmos/config.rs b/crates/relayer/src/chain/cosmos/config.rs index 225b7aa039..a8e91c479f 100644 --- a/crates/relayer/src/chain/cosmos/config.rs +++ b/crates/relayer/src/chain/cosmos/config.rs @@ -2,6 +2,7 @@ use core::time::Duration; use std::path::PathBuf; use byte_unit::Byte; +use monostate::MustBe; use serde_derive::{Deserialize, Serialize}; use tendermint_rpc::Url; @@ -23,6 +24,11 @@ pub mod error; #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] #[serde(deny_unknown_fields)] pub struct CosmosSdkConfig { + /// The type of this chain, must be "CosmosSdk" + /// This is the default if not specified. + #[serde(default)] + pub r#type: MustBe!("CosmosSdk"), + /// The chain's network identifier pub id: ChainId, diff --git a/crates/relayer/src/config.rs b/crates/relayer/src/config.rs index 1427f1e7e1..10721a7348 100644 --- a/crates/relayer/src/config.rs +++ b/crates/relayer/src/config.rs @@ -16,7 +16,7 @@ use core::time::Duration; use std::{fs, fs::File, io::Write, ops::Range, path::Path}; use byte_unit::Byte; -use serde_derive::{Deserialize, Serialize}; +use serde::{Deserialize, Serialize}; use tendermint::block::Height as BlockHeight; use tendermint_rpc::Url; use tendermint_rpc::WebSocketClientUrl; @@ -618,9 +618,18 @@ pub enum EventSourceMode { }, } +// NOTE: +// To work around a limitation of serde, which does not allow +// to specify a default variant if not tag is present, +// every underlying chain config MUST have a field `r#type` of +// type `monotstate::MustBe!("VariantName")`. +// +// For chains other than CosmosSdk, this field MUST NOT be annotated +// with `#[serde(default)]`. +// +// See https://github.com/serde-rs/serde/issues/2231 #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] -#[serde(deny_unknown_fields)] -#[serde(tag = "type")] +#[serde(untagged)] pub enum ChainConfig { CosmosSdk(CosmosSdkConfig), } @@ -770,6 +779,7 @@ mod tests { use super::{load, parse_gas_prices, store_writer}; use crate::config::GasPrice; + use monostate::MustBe; use test_log::test; #[test] @@ -830,6 +840,22 @@ mod tests { assert!(load(path).is_err()); } + #[test] + fn parse_default_chain_type() { + let path = concat!( + env!("CARGO_MANIFEST_DIR"), + "/tests/config/fixtures/relayer_conf_example_default_chain_type.toml" + ); + + let config = load(path).expect("could not parse config"); + + match config.chains[0] { + super::ChainConfig::CosmosSdk(ref config) => { + assert_eq!(config.r#type, MustBe!("CosmosSdk")); + } + } + } + #[test] fn serialize_valid_config() { let path = concat!( diff --git a/crates/relayer/tests/config/fixtures/relayer_conf_example_default_chain_type.toml b/crates/relayer/tests/config/fixtures/relayer_conf_example_default_chain_type.toml new file mode 100644 index 0000000000..6df007f2f7 --- /dev/null +++ b/crates/relayer/tests/config/fixtures/relayer_conf_example_default_chain_type.toml @@ -0,0 +1,56 @@ +[global] +log_level = 'error' + +[mode] + +[mode.clients] +enabled = true +refresh = true +misbehaviour = true + +[mode.connections] +enabled = false + +[mode.channels] +enabled = false + +[mode.packets] +enabled = true +clear_interval = 100 +clear_on_start = true +tx_confirmation = true + +[[chains]] +id = 'chain_A' +rpc_addr = 'http://127.0.0.1:26657' +grpc_addr = 'http://127.0.0.1:9090' +event_source = { mode = 'push', url = 'ws://localhost:26657/websocket', batch_delay = '500ms' } +rpc_timeout = '10s' +account_prefix = 'cosmos' +key_name = 'testkey' +store_prefix = 'ibc' +max_gas = 200000 +gas_price = { price = 0.001, denom = 'stake' } +max_msg_num = 4 +max_tx_size = 1048576 +max_grpc_decoding_size = '4MiB' +clock_drift = '5s' +trusting_period = '14days' +trust_threshold = { numerator = '1', denominator = '3' } +address_type = { derivation = 'cosmos' } + +[[chains]] +id = 'chain_B' +rpc_addr = 'http://127.0.0.1:26557' +grpc_addr = 'http://127.0.0.1:9090' +event_source = { mode = 'push', url = 'ws://localhost:26557/websocket', batch_delay = '500ms' } +rpc_timeout = '10s' +account_prefix = 'cosmos' +key_name = 'testkey' +store_prefix = 'ibc' +gas_price = { price = 0.001, denom = 'stake' } +max_grpc_decoding_size = '5.91 MB' +clock_drift = '5s' +trusting_period = '14days' +trust_threshold = { numerator = '1', denominator = '3' } +address_type = { derivation = 'ethermint', proto_type = { pk_type = '/injective.crypto.v1beta1.ethsecp256k1.PubKey' } } \ No newline at end of file diff --git a/tools/test-framework/src/types/single/node.rs b/tools/test-framework/src/types/single/node.rs index 4fbc20b938..9cf81d3cd0 100644 --- a/tools/test-framework/src/types/single/node.rs +++ b/tools/test-framework/src/types/single/node.rs @@ -155,6 +155,7 @@ impl FullNode { }; Ok(config::ChainConfig::CosmosSdk(CosmosSdkConfig { + r#type: Default::default(), id: self.chain_driver.chain_id.clone(), rpc_addr: Url::from_str(&self.chain_driver.rpc_address())?, grpc_addr: Url::from_str(&self.chain_driver.grpc_address())?,