-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #55 from starkware-libs/lev_dev
feat: add global config and versioning (#55) Co-Authored-By: Uriel Korach <uriel@starkware.co>
- Loading branch information
Showing
9 changed files
with
343 additions
and
1 deletion.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
#![allow(unused_imports)] | ||
use crate::config::node_command; | ||
use crate::config::{ComponentConfig, ComponentExecutionConfig, MempoolNodeConfig}; | ||
use assert_matches::assert_matches; | ||
use papyrus_config::dumping::SerializeConfig; | ||
use papyrus_config::loading::load_and_process_config; | ||
use papyrus_config::presentation::get_config_presentation; | ||
use papyrus_config::validators::ParsedValidationErrors; | ||
use papyrus_config::{SerializationType, SerializedContent, SerializedParam}; | ||
use starknet_gateway::GatewayConfig; | ||
use std::env::{self, args}; | ||
use std::fs::File; | ||
use std::ops::IndexMut; | ||
use std::path::{Path, PathBuf}; | ||
use validator::Validate; | ||
|
||
const TEST_FILES_FOLDER: &str = "./src/test_files"; | ||
const CONFIG_FILE: &str = "mempool_node_config.json"; | ||
|
||
fn get_config_file(file_name: &str) -> Result<MempoolNodeConfig, papyrus_config::ConfigError> { | ||
let config_file = File::open(Path::new(TEST_FILES_FOLDER).join(file_name)).unwrap(); | ||
load_and_process_config::<MempoolNodeConfig>(config_file, node_command(), vec![]) | ||
} | ||
|
||
#[test] | ||
fn test_valid_config() { | ||
// Read the valid config file and validate its content. | ||
let expected_config = MempoolNodeConfig { | ||
components: ComponentConfig { | ||
gateway_component: ComponentExecutionConfig { execute: true }, | ||
mempool_component: ComponentExecutionConfig { execute: false }, | ||
}, | ||
gateway_config: GatewayConfig { | ||
bind_address: String::from("0.0.0.0:8080"), | ||
}, | ||
}; | ||
let loaded_config = get_config_file(CONFIG_FILE).unwrap(); | ||
|
||
assert!(loaded_config.validate().is_ok()); | ||
assert_eq!(loaded_config, expected_config); | ||
} | ||
|
||
#[test] | ||
fn test_components_config() { | ||
// Read the valid config file and check that the validator finds no errors. | ||
let mut config = get_config_file(CONFIG_FILE).unwrap(); | ||
assert!(config.validate().is_ok()); | ||
|
||
// Invalidate the gateway component and check that the validator finds an error. | ||
config.components.gateway_component.execute = false; | ||
|
||
assert_matches!(config.validate(), Err(e) => { | ||
let parse_err = ParsedValidationErrors::from(e); | ||
let mut error_msg = String::new(); | ||
for error in parse_err.0 { | ||
if error.param_path == "components.__all__" { | ||
error_msg.push_str(&error.code); | ||
break; | ||
} | ||
} | ||
assert_eq!(error_msg, "Invalid components configuration."); | ||
}); | ||
|
||
// Validate the mempool component and check that the validator finds no errors. | ||
config.components.mempool_component.execute = true; | ||
assert!(config.validate().is_ok()); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
#[cfg(test)] | ||
mod config_test; | ||
|
||
use std::collections::BTreeMap; | ||
use std::fs::File; | ||
use std::path::Path; | ||
|
||
use clap::Command; | ||
use papyrus_config::dumping::{append_sub_config_name, ser_param, SerializeConfig}; | ||
use papyrus_config::loading::load_and_process_config; | ||
use papyrus_config::ParamPrivacyInput; | ||
use papyrus_config::{ConfigError, ParamPath, SerializedParam}; | ||
use serde::{Deserialize, Serialize}; | ||
use starknet_gateway::GatewayConfig; | ||
use validator::{Validate, ValidationError}; | ||
|
||
use crate::version::VERSION_FULL; | ||
|
||
// The path of the default configuration file, provided as part of the crate. | ||
pub const DEFAULT_CONFIG_PATH: &str = "config/default_config.json"; | ||
|
||
/// The single crate configuration. | ||
#[derive(Clone, Debug, Serialize, Deserialize, Validate, PartialEq)] | ||
pub struct ComponentExecutionConfig { | ||
pub execute: bool, | ||
} | ||
|
||
impl SerializeConfig for ComponentExecutionConfig { | ||
fn dump(&self) -> BTreeMap<ParamPath, SerializedParam> { | ||
BTreeMap::from_iter([ser_param( | ||
"execute", | ||
&self.execute, | ||
"The component execution flag.", | ||
ParamPrivacyInput::Public, | ||
)]) | ||
} | ||
} | ||
|
||
impl Default for ComponentExecutionConfig { | ||
fn default() -> Self { | ||
Self { execute: true } | ||
} | ||
} | ||
|
||
/// The components configuration. | ||
#[derive(Clone, Debug, Serialize, Deserialize, Validate, PartialEq, Default)] | ||
#[validate(schema(function = "validate_components_config"))] | ||
pub struct ComponentConfig { | ||
pub gateway_component: ComponentExecutionConfig, | ||
pub mempool_component: ComponentExecutionConfig, | ||
} | ||
|
||
impl SerializeConfig for ComponentConfig { | ||
fn dump(&self) -> BTreeMap<ParamPath, SerializedParam> { | ||
#[allow(unused_mut)] | ||
let mut sub_configs = vec![ | ||
append_sub_config_name(self.gateway_component.dump(), "gateway_component"), | ||
append_sub_config_name(self.mempool_component.dump(), "mempool_component"), | ||
]; | ||
|
||
sub_configs.into_iter().flatten().collect() | ||
} | ||
} | ||
|
||
pub fn validate_components_config(components: &ComponentConfig) -> Result<(), ValidationError> { | ||
if components.gateway_component.execute || components.mempool_component.execute { | ||
return Ok(()); | ||
} | ||
|
||
let mut error = ValidationError::new("Invalid components configuration."); | ||
error.message = Some("At least one component should be allowed to execute.".into()); | ||
Err(error) | ||
} | ||
|
||
/// The configurations of the various components of the node. | ||
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Validate, Default)] | ||
pub struct MempoolNodeConfig { | ||
#[validate] | ||
pub components: ComponentConfig, | ||
#[validate] | ||
pub gateway_config: GatewayConfig, | ||
} | ||
|
||
impl SerializeConfig for MempoolNodeConfig { | ||
fn dump(&self) -> BTreeMap<ParamPath, SerializedParam> { | ||
#[allow(unused_mut)] | ||
let mut sub_configs = vec![ | ||
append_sub_config_name(self.components.dump(), "components"), | ||
append_sub_config_name(self.gateway_config.dump(), "gateway_config"), | ||
]; | ||
|
||
sub_configs.into_iter().flatten().collect() | ||
} | ||
} | ||
|
||
impl MempoolNodeConfig { | ||
/// Creates a config object. Selects the values from the default file and from resources with | ||
/// higher priority. | ||
fn load_and_process_config_file( | ||
args: Vec<String>, | ||
config_file_name: Option<&str>, | ||
) -> Result<Self, ConfigError> { | ||
let config_file_name = match config_file_name { | ||
Some(file_name) => file_name, | ||
None => DEFAULT_CONFIG_PATH, | ||
}; | ||
|
||
let default_config_file = File::open(Path::new(config_file_name))?; | ||
load_and_process_config(default_config_file, node_command(), args) | ||
} | ||
|
||
pub fn load_and_process(args: Vec<String>) -> Result<Self, ConfigError> { | ||
Self::load_and_process_config_file(args, None) | ||
} | ||
pub fn load_and_process_file( | ||
args: Vec<String>, | ||
config_file_name: &str, | ||
) -> Result<Self, ConfigError> { | ||
Self::load_and_process_config_file(args, Some(config_file_name)) | ||
} | ||
} | ||
|
||
/// The command line interface of this node. | ||
pub fn node_command() -> Command { | ||
Command::new("Mempool") | ||
.version(VERSION_FULL) | ||
.about("Mempool is a StarkNet mempool node written in Rust.") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
pub mod config; | ||
pub mod version; |
18 changes: 18 additions & 0 deletions
18
crates/mempool_node/src/test_files/mempool_node_config.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
{ | ||
"components.gateway_component.execute": { | ||
"description": "The component execution flag.", | ||
"value": true, | ||
"privacy": "Public" | ||
}, | ||
"components.mempool_component.execute": { | ||
"description": "The component execution flag.", | ||
"value": false, | ||
"privacy": "Public" | ||
}, | ||
"gateway_config.bind_address": { | ||
"description": "The server bind addres of a gateway.", | ||
"value": "0.0.0.0:8080", | ||
"privacy": "Public" | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
#[cfg(test)] | ||
#[path = "version_test.rs"] | ||
mod version_test; | ||
|
||
/// Major version component of the current release. | ||
const VERSION_MAJOR: u32 = 0; | ||
|
||
/// Minor version component of the current release. | ||
const VERSION_MINOR: u32 = 0; | ||
|
||
/// Patch version component of the current release. | ||
const VERSION_PATCH: u32 = 0; | ||
|
||
/// Version metadata to append to the version string. | ||
/// Expected values are `dev` and `stable`. | ||
#[allow(dead_code)] | ||
const VERSION_META: Metadata = Metadata::Dev; | ||
|
||
/// Textual version string. | ||
pub const VERSION: &str = version_str(); | ||
/// Textual version string including the metadata. | ||
pub const VERSION_FULL: &str = full_version_str(); | ||
|
||
#[allow(dead_code)] | ||
const DEV_VERSION_META: &str = "dev"; | ||
#[allow(dead_code)] | ||
const STABLE_VERSION_META: &str = "stable"; | ||
|
||
#[allow(dead_code)] | ||
#[derive(PartialEq)] | ||
enum Metadata { | ||
Dev, | ||
Stable, | ||
} | ||
|
||
#[cfg_attr(coverage_nightly, coverage_attribute)] | ||
const fn version_str() -> &'static str { | ||
const_format::concatcp!(VERSION_MAJOR, ".", VERSION_MINOR, ".", VERSION_PATCH) | ||
} | ||
|
||
#[cfg_attr(coverage_nightly, coverage_attribute)] | ||
const fn full_version_str() -> &'static str { | ||
match VERSION_META { | ||
Metadata::Dev => const_format::concatcp!(VERSION, "-", DEV_VERSION_META), | ||
Metadata::Stable => VERSION, | ||
} | ||
} | ||
|
||
#[allow(dead_code)] | ||
const fn metadata_str(metadata: Metadata) -> &'static str { | ||
match metadata { | ||
Metadata::Dev => DEV_VERSION_META, | ||
Metadata::Stable => STABLE_VERSION_META, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
use pretty_assertions::assert_eq; | ||
|
||
#[test] | ||
fn version() { | ||
let expected_version = format!( | ||
"{}.{}.{}", | ||
super::VERSION_MAJOR, | ||
super::VERSION_MINOR, | ||
super::VERSION_PATCH | ||
); | ||
assert_eq!(super::VERSION, expected_version); | ||
|
||
let expected_version_with_meta = match super::VERSION_META { | ||
crate::version::Metadata::Dev => { | ||
format!( | ||
"{}-{}", | ||
expected_version, | ||
super::metadata_str(super::VERSION_META) | ||
) | ||
} | ||
crate::version::Metadata::Stable => expected_version, | ||
}; | ||
assert_eq!(super::VERSION_FULL, expected_version_with_meta); | ||
} |