The home for Hyperlane core contracts, sdk packages, and other infrastructure
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
hyperlane-monorepo/rust/agents/validator/src/settings.rs

112 lines
3.5 KiB

//! Configuration
Better Agent Configuration Parsing (#2070) ### Description This is a significant change to how we parse user configs. The main goal of this PR is to give a clear path and env key to any errors that are encountered when parsing configuration. In order to accomplish this, I have crated a new trait `FromRawConf` which defines a set of steps to validate and convert individual fields. Also for every major config struct, there is now a `Raw*` variant of it which is used by the `config` library to reduce errors that occur during deserialization itself. `Raw*` types should always use the most basic form of a value, such as `String`, `StrOrInt`, `bool`, and ideally optional in all cases. Missing values should be handled during the raw conversion and not by `config`. I also needed to make changes to a number of types stored in the parsed config types to force validation forward to the parsing step instead of doing it when we read the config value. This also required me to create a filter to prevent trying to validate certain configs that we would not ever need to load. These changes can also be built on later to support something other than `config` if we choose to, or add support for merging configs from multiple sources since everything is optional. ### Drive-by changes - Default to `http` for connection type - Default to no gas payment enforcement if not specified instead of failing - `ChainSetup` -> `ChainConf` - `GasPaymentEnforcementConfig` -> `GasPaymentEnforcementConf` - Made ethereum connection configuration more forgiving - Moved hyperlane base settings from `mod.rs` to `base.rs` - Moved config chain tests in hyperlane core to `tests` dir to fix a cyclical import problem - Extension traits to help with config in hyperlane core - Moved `StrOrInt` to new hyperlane core `config` module - Support for parsing `U256` from `StrOrInt` - Removed `HexString` type which is now redundant - Updated base settings to use hyperlane domain - Use `heyKey` as signer type if `type` is not specified and `key` is - Moved hyperlane ethereum chain config to a new module ### Related issues - Fixes #2033 - Fixes #2012 ### Backward compatibility _Are these changes backward compatible?_ Yes - This should take in configs in the same shape but be more forgiving in a few places _Are there any infrastructure implications, e.g. changes that would prohibit deploying older commits using this infra tooling?_ None ### Testing _What kind of testing have these changes undergone?_ Manual Unit Test
2 years ago
use std::time::Duration;
use eyre::eyre;
use hyperlane_base::{
decl_settings, CheckpointSyncerConf, RawCheckpointSyncerConf, RawSignerConf, Settings,
SignerConf,
};
use hyperlane_core::config::*;
use hyperlane_core::HyperlaneDomain;
decl_settings!(Validator,
Parsed {
/// Chain to validate messages on
origin_chain: HyperlaneDomain,
/// The validator attestation signer
validator: SignerConf,
/// The checkpoint syncer configuration
checkpoint_syncer: CheckpointSyncerConf,
/// The reorg_period in blocks
reorg_period: u64,
/// How frequently to check for new checkpoints
interval: Duration,
},
Raw {
// Name of the chain to validate message on
originchainname: Option<String>,
/// The validator attestation signer
#[serde(default)]
validator: RawSignerConf,
/// The checkpoint syncer configuration
checkpointsyncer: Option<RawCheckpointSyncerConf>,
/// The reorg_period in blocks
reorgperiod: Option<StrOrInt>,
/// How frequently to check for new checkpoints
interval: Option<StrOrInt>,
},
);
impl FromRawConf<'_, RawValidatorSettings> for ValidatorSettings {
fn from_config_filtered(
raw: RawValidatorSettings,
cwp: &ConfigPath,
_filter: (),
) -> ConfigResult<Self> {
let mut err = ConfigParsingError::default();
let validator = raw
.validator
.parse_config(&cwp.join("validator"))
.take_config_err(&mut err);
let checkpoint_syncer = raw
.checkpointsyncer
.ok_or_else(|| eyre!("Missing `checkpointsyncer`"))
.take_err(&mut err, || cwp + "checkpointsyncer")
.and_then(|r| {
r.parse_config(&cwp.join("checkpointsyncer"))
.take_config_err(&mut err)
});
let reorg_period = raw
.reorgperiod
.ok_or_else(|| eyre!("Missing `reorgperiod`"))
.take_err(&mut err, || cwp + "reorgperiod")
.and_then(|r| r.try_into().take_err(&mut err, || cwp + "reorgperiod"));
let interval = raw
.interval
.ok_or_else(|| eyre!("Missing `interval`"))
.take_err(&mut err, || cwp + "interval")
.and_then(|r| {
r.try_into()
.map(Duration::from_secs)
.take_err(&mut err, || cwp + "interval")
});
let Some(origin_chain_name) = raw
.originchainname
.ok_or_else(|| eyre!("Missing `originchainname`"))
.take_err(&mut err, || cwp + "originchainname")
else { return Err(err) };
let base = raw
.base
.parse_config_with_filter::<Settings>(
cwp,
Some(&[origin_chain_name.as_ref()].into_iter().collect()),
)
.take_config_err(&mut err);
let origin_chain = if let Some(base) = &base {
base.lookup_domain(&origin_chain_name)
.take_err(&mut err, || cwp + "originchainname")
} else {
None
};
err.into_result()?;
Ok(Self {
base: base.unwrap(),
origin_chain: origin_chain.unwrap(),
validator: validator.unwrap(),
checkpoint_syncer: checkpoint_syncer.unwrap(),
reorg_period: reorg_period.unwrap(),
interval: interval.unwrap(),
})
}
}