Skip to content

Commit

Permalink
Improve error message when deserializing an invalid chain config
Browse files Browse the repository at this point in the history
Error messages when deserializing an invalid chain config have gotten a lot worse since #3787.

For example, when mistyping the `gas_multiplier` field as `gas_multiplie` in the per-chain config:

```
data did not match any variant of untagged enum ChainConfig for key `chains` at line 424 column 1
```

After this commit (same message as before #3787):

```
invalid CosmosSdk config: unknown field `gas_multiplie`, expected one of `id`, `rpc_addr`, `grpc_addr`, `event_source`,
`rpc_timeout`, `trusted_node`, `account_prefix`, `key_name`, `key_store_type`, `key_store_folder`, `store_prefix`,
`default_gas`, `max_gas`, `genesis_restart`, `gas_adjustment`, `gas_multiplier`, `fee_granter`, `max_msg_num`,
`max_tx_size`, `max_grpc_decoding_size`, `query_packets_chunk_size`, `clock_drift`, `max_block_time`, `trusting_period`,
`client_refresh_rate`, `ccv_consumer_chain`, `memo_prefix`, `sequential_batch_tx`, `proof_specs`, `trust_threshold`,
`gas_price`, `packet_filter`, `address_type`, `extension_options`, `compat_mode`, `clear_interval`
for key `chains` at line 424 column 1
```

For this, we now use a custom deserializer for ChainConfig instead of relying on an untagged enum.
  • Loading branch information
romac committed Jan 22, 2024
1 parent 90ebd6b commit 5020a7f
Showing 1 changed file with 34 additions and 11 deletions.
45 changes: 34 additions & 11 deletions crates/relayer/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -618,18 +618,13 @@ pub enum EventSourceMode {
},
}

// NOTE:
// To work around a limitation of serde, which does not allow
// 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(untagged)]
// every underlying chain config struct MUST have a field `r#type` with
// type `monotstate::MustBe!("VariantName")`, eg. the `CosmosSdkConfig`
// struct has a field `r#type: MustBe!("CosmosSdk")`.
#[derive(Clone, Debug, PartialEq, Serialize)]
#[serde(tag = "type")]
pub enum ChainConfig {
CosmosSdk(CosmosSdkConfig),
}
Expand Down Expand Up @@ -704,6 +699,34 @@ impl ChainConfig {
}
}

impl<'de> Deserialize<'de> for ChainConfig {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let value = toml::Value::deserialize(deserializer)?;

let type_value = value
.get("type")
.cloned()
.unwrap_or_else(|| toml::Value::String("CosmosSdk".to_string()));

let type_str = type_value
.as_str()
.ok_or_else(|| serde::de::Error::custom("invalid chain type, must be a string"))?;

match type_str {
"CosmosSdk" => CosmosSdkConfig::deserialize(value)
.map(Self::CosmosSdk)
.map_err(|e| serde::de::Error::custom(format!("invalid CosmosSdk config: {e}"))),

chain_type => Err(serde::de::Error::custom(format!(
"unknown chain type: {chain_type}",
))),
}
}
}

/// Attempt to load and parse the TOML config file as a `Config`.
pub fn load(path: impl AsRef<Path>) -> Result<Config, Error> {
let config_toml = std::fs::read_to_string(&path).map_err(Error::io)?;
Expand Down

0 comments on commit 5020a7f

Please sign in to comment.