Improve config errors (#1776)

* Remove path to error as it was not working

* Better domain parsing errors

* Locked min version of config lib

* Improve error messages for config loading
pull/1785/head
Mattie Conover 2 years ago committed by GitHub
parent aeb056336c
commit 4b7e7ca9bb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 10
      rust/Cargo.lock
  2. 2
      rust/agents/relayer/Cargo.toml
  3. 2
      rust/agents/scraper/Cargo.toml
  4. 2
      rust/agents/validator/Cargo.toml
  5. 3
      rust/hyperlane-base/Cargo.toml
  6. 56
      rust/hyperlane-base/src/settings/chains.rs
  7. 11
      rust/hyperlane-base/src/settings/loader.rs
  8. 2
      rust/hyperlane-core/Cargo.toml
  9. 4
      rust/hyperlane-core/src/chain.rs

10
rust/Cargo.lock generated

@ -2718,7 +2718,6 @@ dependencies = [
"rusoto_s3", "rusoto_s3",
"serde", "serde",
"serde_json", "serde_json",
"serde_path_to_error",
"thiserror", "thiserror",
"tokio", "tokio",
"tracing", "tracing",
@ -5014,15 +5013,6 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "serde_path_to_error"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26b04f22b563c91331a10074bda3dd5492e3cc39d56bd557e91c0af42b6c7341"
dependencies = [
"serde",
]
[[package]] [[package]]
name = "serde_repr" name = "serde_repr"
version = "0.1.10" version = "0.1.10"

@ -6,7 +6,7 @@ edition = "2021"
[dependencies] [dependencies]
tokio = { version = "1", features = ["rt", "macros"] } tokio = { version = "1", features = ["rt", "macros"] }
coingecko = { git = "https://github.com/hyperlane-xyz/coingecko-rs", tag = "2022-09-14-02" } coingecko = { git = "https://github.com/hyperlane-xyz/coingecko-rs", tag = "2022-09-14-02" }
config = "0.13" config = "~0.13.3"
serde = {version = "1.0", features = ["derive"]} serde = {version = "1.0", features = ["derive"]}
serde_json = { version = "1.0", default-features = false } serde_json = { version = "1.0", default-features = false }
ethers = { git = "https://github.com/hyperlane-xyz/ethers-rs", tag = "2023-01-10-04" } ethers = { git = "https://github.com/hyperlane-xyz/ethers-rs", tag = "2023-01-10-04" }

@ -6,7 +6,7 @@ edition = "2021"
[dependencies] [dependencies]
async-trait = { version = "0.1", default-features = false } async-trait = { version = "0.1", default-features = false }
chrono = "0.4" chrono = "0.4"
config = "0.13" config = "~0.13.3"
ethers = { git = "https://github.com/hyperlane-xyz/ethers-rs", tag = "2023-01-10-04" } ethers = { git = "https://github.com/hyperlane-xyz/ethers-rs", tag = "2023-01-10-04" }
eyre = "0.6" eyre = "0.6"
itertools = "0.10" itertools = "0.10"

@ -5,7 +5,7 @@ edition = "2021"
[dependencies] [dependencies]
tokio = { version = "1", features = ["rt", "macros"] } tokio = { version = "1", features = ["rt", "macros"] }
config = "0.13" config = "~0.13.3"
serde = "1.0" serde = "1.0"
serde_json = { version = "1.0", default-features = false } serde_json = { version = "1.0", default-features = false }
ethers = { git = "https://github.com/hyperlane-xyz/ethers-rs", tag = "2023-01-10-04" } ethers = { git = "https://github.com/hyperlane-xyz/ethers-rs", tag = "2023-01-10-04" }

@ -7,10 +7,9 @@ edition = "2021"
[dependencies] [dependencies]
# Main block # Main block
tokio = { version = "1", features = ["rt", "macros"] } tokio = { version = "1", features = ["rt", "macros"] }
config = "0.13" config = "~0.13.3"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = { version = "1.0", default-features = false } serde_json = { version = "1.0", default-features = false }
serde_path_to_error = "0.1"
ethers = { git = "https://github.com/hyperlane-xyz/ethers-rs", tag = "2023-01-10-04" } ethers = { git = "https://github.com/hyperlane-xyz/ethers-rs", tag = "2023-01-10-04" }
fuels = "0.33" fuels = "0.33"
thiserror = "1.0" thiserror = "1.0"

@ -143,21 +143,25 @@ impl ChainSetup {
&self, &self,
metrics: &CoreMetrics, metrics: &CoreMetrics,
) -> Result<Box<dyn HyperlaneProvider>> { ) -> Result<Box<dyn HyperlaneProvider>> {
let ctx = "Building provider";
match &self.chain { match &self.chain {
ChainConf::Ethereum(conf) => { ChainConf::Ethereum(conf) => {
let locator = self.locator("0x0000000000000000000000000000000000000000")?; let locator = self
.locator("0x0000000000000000000000000000000000000000")
.context(ctx)?;
self.build_ethereum(conf, &locator, metrics, h_eth::HyperlaneProviderBuilder {}) self.build_ethereum(conf, &locator, metrics, h_eth::HyperlaneProviderBuilder {})
.await .await
} }
ChainConf::Fuel(_) => todo!(), ChainConf::Fuel(_) => todo!(),
} }
.context("Building provider") .context(ctx)
} }
/// Try to convert the chain setting into a Mailbox contract /// Try to convert the chain setting into a Mailbox contract
pub async fn build_mailbox(&self, metrics: &CoreMetrics) -> Result<Box<dyn Mailbox>> { pub async fn build_mailbox(&self, metrics: &CoreMetrics) -> Result<Box<dyn Mailbox>> {
let locator = self.locator(&self.addresses.mailbox)?; let ctx = "Building provider";
let locator = self.locator(&self.addresses.mailbox).context(ctx)?;
match &self.chain { match &self.chain {
ChainConf::Ethereum(conf) => { ChainConf::Ethereum(conf) => {
@ -166,13 +170,13 @@ impl ChainSetup {
} }
ChainConf::Fuel(conf) => { ChainConf::Fuel(conf) => {
let wallet = self.fuel_signer().await?; let wallet = self.fuel_signer().await.context(ctx)?;
hyperlane_fuel::FuelMailbox::new(conf, locator, wallet) hyperlane_fuel::FuelMailbox::new(conf, locator, wallet)
.map(|m| Box::new(m) as Box<dyn Mailbox>) .map(|m| Box::new(m) as Box<dyn Mailbox>)
.map_err(Into::into) .map_err(Into::into)
} }
} }
.context("Building mailbox") .context(ctx)
} }
/// Try to convert the chain settings into a mailbox indexer /// Try to convert the chain settings into a mailbox indexer
@ -180,7 +184,8 @@ impl ChainSetup {
&self, &self,
metrics: &CoreMetrics, metrics: &CoreMetrics,
) -> Result<Box<dyn MailboxIndexer>> { ) -> Result<Box<dyn MailboxIndexer>> {
let locator = self.locator(&self.addresses.mailbox)?; let ctx = "Building mailbox indexer";
let locator = self.locator(&self.addresses.mailbox).context(ctx)?;
match &self.chain { match &self.chain {
ChainConf::Ethereum(conf) => { ChainConf::Ethereum(conf) => {
@ -197,7 +202,7 @@ impl ChainSetup {
ChainConf::Fuel(_) => todo!(), ChainConf::Fuel(_) => todo!(),
} }
.context("Building mailbox indexer") .context(ctx)
} }
/// Try to convert the chain setting into an interchain gas paymaster /// Try to convert the chain setting into an interchain gas paymaster
@ -206,7 +211,10 @@ impl ChainSetup {
&self, &self,
metrics: &CoreMetrics, metrics: &CoreMetrics,
) -> Result<Box<dyn InterchainGasPaymaster>> { ) -> Result<Box<dyn InterchainGasPaymaster>> {
let locator = self.locator(&self.addresses.interchain_gas_paymaster)?; let ctx = "Building IGP";
let locator = self
.locator(&self.addresses.interchain_gas_paymaster)
.context(ctx)?;
match &self.chain { match &self.chain {
ChainConf::Ethereum(conf) => { ChainConf::Ethereum(conf) => {
@ -221,7 +229,7 @@ impl ChainSetup {
ChainConf::Fuel(_) => todo!(), ChainConf::Fuel(_) => todo!(),
} }
.context("Building IGP") .context(ctx)
} }
/// Try to convert the chain settings into a IGP indexer /// Try to convert the chain settings into a IGP indexer
@ -229,7 +237,10 @@ impl ChainSetup {
&self, &self,
metrics: &CoreMetrics, metrics: &CoreMetrics,
) -> Result<Box<dyn InterchainGasPaymasterIndexer>> { ) -> Result<Box<dyn InterchainGasPaymasterIndexer>> {
let locator = self.locator(&self.addresses.interchain_gas_paymaster)?; let ctx = "Building IGP indexer";
let locator = self
.locator(&self.addresses.interchain_gas_paymaster)
.context(ctx)?;
match &self.chain { match &self.chain {
ChainConf::Ethereum(conf) => { ChainConf::Ethereum(conf) => {
@ -238,7 +249,12 @@ impl ChainSetup {
&locator, &locator,
metrics, metrics,
h_eth::InterchainGasPaymasterIndexerBuilder { h_eth::InterchainGasPaymasterIndexerBuilder {
mailbox_address: self.addresses.mailbox.parse()?, mailbox_address: self
.addresses
.mailbox
.parse()
.context("Parsing mailbox address")
.context(ctx)?,
finality_blocks: self.finality_blocks(), finality_blocks: self.finality_blocks(),
}, },
) )
@ -247,7 +263,7 @@ impl ChainSetup {
ChainConf::Fuel(_) => todo!(), ChainConf::Fuel(_) => todo!(),
} }
.context("Building IGP indexer") .context(ctx)
} }
/// Try to convert the chain setting into a Multisig Ism contract /// Try to convert the chain setting into a Multisig Ism contract
@ -256,8 +272,12 @@ impl ChainSetup {
address: H256, address: H256,
metrics: &CoreMetrics, metrics: &CoreMetrics,
) -> Result<Box<dyn MultisigIsm>> { ) -> Result<Box<dyn MultisigIsm>> {
let ctx = "Building multisig ISM";
let locator = ContractLocator { let locator = ContractLocator {
domain: self.domain()?, domain: self
.domain()
.context("Invalid domain for locating contract")
.context(ctx)?,
address, address,
}; };
@ -269,7 +289,7 @@ impl ChainSetup {
ChainConf::Fuel(_) => todo!(), ChainConf::Fuel(_) => todo!(),
} }
.context("Building multisig ISM") .context(ctx)
} }
/// Get the domain for this chain setup /// Get the domain for this chain setup
@ -348,15 +368,17 @@ impl ChainSetup {
} }
fn locator(&self, address: &str) -> Result<ContractLocator> { fn locator(&self, address: &str) -> Result<ContractLocator> {
let domain = self.domain()?; let domain = self
.domain()
.context("Invalid domain for locating contract")?;
let address = match self.chain { let address = match self.chain {
ChainConf::Ethereum(_) => address ChainConf::Ethereum(_) => address
.parse::<ethers::types::Address>() .parse::<ethers::types::Address>()
.context("Invalid ethereum address")? .context("Invalid ethereum address for locating contract")?
.into(), .into(),
ChainConf::Fuel(_) => address ChainConf::Fuel(_) => address
.parse::<fuels::tx::ContractId>() .parse::<fuels::tx::ContractId>()
.map_err(|e| eyre!("Invalid fuel contract id: {e}"))? .map_err(|e| eyre!("Invalid fuel contract id for locating contract: {e}"))?
.into_h256(), .into_h256(),
}; };

@ -1,5 +1,6 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::env; use std::env;
use std::error::Error;
use config::{Config, Environment, File}; use config::{Config, Environment, File};
use eyre::{Context, Result}; use eyre::{Context, Result};
@ -74,15 +75,19 @@ pub(crate) fn load_settings_object<'de, T: Deserialize<'de>, S: AsRef<str>>(
) )
.build()?; .build()?;
let formatted_config = format!("{:#?}", config_deserializer).replace('\n', "\\n"); let formatted_config = format!("{:#?}", config_deserializer).replace('\n', "\\n");
match serde_path_to_error::deserialize(config_deserializer) { match Config::try_deserialize(config_deserializer) {
Ok(cfg) => Ok(cfg), Ok(cfg) => Ok(cfg),
Err(err) => { Err(err) => {
println!( println!(
"Error during deserialization, showing the config for debugging: {}", "Error during deserialization, showing the config for debugging: {}",
formatted_config formatted_config
); );
let ctx = format!("Invalid config at `{}` {:?}", err.path(), err); if let Some(source_err) = err.source() {
Err(err).context(ctx) let source = format!("Config error source: {source_err}");
Err(err).context(source)
} else {
Err(err.into())
}
} }
} }
} }

@ -10,7 +10,7 @@ auto_impl = "1.0"
ethers = { git = "https://github.com/hyperlane-xyz/ethers-rs", tag = "2023-01-10-04" } ethers = { git = "https://github.com/hyperlane-xyz/ethers-rs", tag = "2023-01-10-04" }
ethers-signers = { git = "https://github.com/hyperlane-xyz/ethers-rs", tag = "2023-01-10-04", features=["aws"] } ethers-signers = { git = "https://github.com/hyperlane-xyz/ethers-rs", tag = "2023-01-10-04", features=["aws"] }
ethers-providers = { git = "https://github.com/hyperlane-xyz/ethers-rs", tag = "2023-01-10-04", features=["ws", "rustls"] } ethers-providers = { git = "https://github.com/hyperlane-xyz/ethers-rs", tag = "2023-01-10-04", features=["ws", "rustls"] }
config = "0.13" config = "~0.13.3"
hex = "0.4.3" hex = "0.4.3"
sha3 = "0.10" sha3 = "0.10"
lazy_static = "*" lazy_static = "*"

@ -259,10 +259,10 @@ impl HyperlaneDomain {
if name == domain.as_str() { if name == domain.as_str() {
Ok(HyperlaneDomain::Known(domain)) Ok(HyperlaneDomain::Known(domain))
} else { } else {
Err("Chain name does not match the name of a known domain id; the config is probably wrong.") Err("Chain name does not match the name of a known domain id; the chain name is probably misspelled.")
} }
} else if name.as_str().parse::<KnownHyperlaneDomain>().is_ok() { } else if name.as_str().parse::<KnownHyperlaneDomain>().is_ok() {
Err("Chain name is known the domain is incorrect; the config is probably wrong.") Err("Chain name implies a different domain than the domain id provided; the domain id is probably wrong.")
} else { } else {
Ok(HyperlaneDomain::Unknown { Ok(HyperlaneDomain::Unknown {
domain_id, domain_id,

Loading…
Cancel
Save