From 832cd93dfb96cb1ca8a19b4b126429fa63aaa6ba Mon Sep 17 00:00:00 2001 From: ltitanb Date: Wed, 11 Sep 2024 23:58:17 +0100 Subject: [PATCH 1/6] tidy up env names + logs --- bin/src/lib.rs | 2 +- crates/cli/src/docker_init.rs | 77 ++++++++++++++------------- crates/common/src/config/constants.rs | 58 +++++++++++++------- crates/common/src/config/log.rs | 30 ++++++++++- crates/common/src/config/pbs.rs | 4 +- crates/common/src/config/signer.rs | 4 +- crates/common/src/utils.rs | 40 ++++++-------- examples/builder_log/Cargo.toml | 1 + examples/builder_log/src/main.rs | 6 ++- examples/da_commit/src/main.rs | 2 +- examples/status_api/src/main.rs | 2 +- 11 files changed, 136 insertions(+), 90 deletions(-) diff --git a/bin/src/lib.rs b/bin/src/lib.rs index eb9f5067..44cf8552 100644 --- a/bin/src/lib.rs +++ b/bin/src/lib.rs @@ -7,7 +7,7 @@ pub mod prelude { }, config::{ load_builder_module_config, load_commit_module_config, load_pbs_config, - load_pbs_custom_config, StartCommitModuleConfig, + load_pbs_custom_config, LogsSettings, StartCommitModuleConfig, }, pbs::{BuilderEvent, BuilderEventClient, OnBuilderApiEvent}, signer::{BlsPublicKey, BlsSignature, EcdsaPublicKey, EcdsaSignature}, diff --git a/crates/cli/src/docker_init.rs b/crates/cli/src/docker_init.rs index 2a40edde..06effb74 100644 --- a/crates/cli/src/docker_init.rs +++ b/crates/cli/src/docker_init.rs @@ -2,11 +2,11 @@ use std::{path::Path, vec}; use cb_common::{ config::{ - CommitBoostConfig, LogsSettings, ModuleKind, BUILDER_SERVER_ENV, CB_BASE_LOG_PATH, - CB_CONFIG_ENV, CB_CONFIG_NAME, JWTS_ENV, MAX_LOG_FILES_ENV, METRICS_SERVER_ENV, - MODULE_ID_ENV, MODULE_JWT_ENV, PBS_MODULE_NAME, RUST_LOG_ENV, SIGNER_DIR_KEYS, - SIGNER_DIR_KEYS_ENV, SIGNER_DIR_SECRETS, SIGNER_DIR_SECRETS_ENV, SIGNER_KEYS, - SIGNER_KEYS_ENV, SIGNER_MODULE_NAME, SIGNER_SERVER_ENV, USE_FILE_LOGS_ENV, + CommitBoostConfig, LogsSettings, ModuleKind, BUILDER_SERVER_ENV, CB_CONFIG_DEFAULT, + CB_CONFIG_ENV, JWTS_ENV, LOGS_DIR_DEFAULT, LOGS_DIR_ENV, METRICS_SERVER_ENV, MODULE_ID_ENV, + MODULE_JWT_ENV, PBS_MODULE_NAME, SIGNER_DEFAULT, SIGNER_DIR_KEYS_DEFAULT, + SIGNER_DIR_KEYS_ENV, SIGNER_DIR_SECRETS, SIGNER_DIR_SECRETS_ENV, SIGNER_KEYS_ENV, + SIGNER_MODULE_NAME, SIGNER_SERVER_ENV, }, loader::SignerLoader, utils::random_jwt, @@ -38,26 +38,13 @@ pub fn handle_docker_init(config_path: String, output_dir: String) -> Result<()> let cb_config = CommitBoostConfig::from_file(&config_path)?; let metrics_enabled = cb_config.metrics.is_some(); - - // Logging - let logging_envs = if let Some(log_config) = &cb_config.logs { - let mut envs = vec![ - get_env_bool(USE_FILE_LOGS_ENV, true), - get_env_val(RUST_LOG_ENV, &log_config.log_level), - ]; - if let Some(max_files) = log_config.max_log_files { - envs.push(get_env_uval(MAX_LOG_FILES_ENV, max_files as u64)) - } - envs - } else { - vec![] - }; + let log_to_file = cb_config.logs.is_some(); let mut services = IndexMap::new(); let mut volumes = IndexMap::new(); // config volume to pass to all services - let config_volume = Volumes::Simple(format!("./{}:{}:ro", config_path, CB_CONFIG_NAME)); + let config_volume = Volumes::Simple(format!("./{}:{}:ro", config_path, CB_CONFIG_DEFAULT)); let mut jwts = IndexMap::new(); // envs to write in .env file @@ -102,7 +89,7 @@ pub fn handle_docker_init(config_path: String, output_dir: String) -> Result<()> // module ids are assumed unique, so envs dont override each other let mut module_envs = IndexMap::from([ get_env_val(MODULE_ID_ENV, &module.id), - get_env_val(CB_CONFIG_ENV, CB_CONFIG_NAME), + get_env_val(CB_CONFIG_ENV, CB_CONFIG_DEFAULT), get_env_interp(MODULE_JWT_ENV, &jwt_name), get_env_val(SIGNER_SERVER_ENV, &signer_server), ]); @@ -121,7 +108,10 @@ pub fn handle_docker_init(config_path: String, output_dir: String) -> Result<()> let (key, val) = get_env_uval(METRICS_SERVER_ENV, metrics_port as u64); module_envs.insert(key, val); } - module_envs.extend(logging_envs.clone()); + if log_to_file { + let (key, val) = get_env_val(LOGS_DIR_ENV, LOGS_DIR_DEFAULT); + module_envs.insert(key, val); + } envs.insert(jwt_name.clone(), jwt.clone()); jwts.insert(module.id.clone(), jwt); @@ -155,15 +145,18 @@ pub fn handle_docker_init(config_path: String, output_dir: String) -> Result<()> // module ids are assumed unique, so envs dont override each other let mut module_envs = IndexMap::from([ get_env_val(MODULE_ID_ENV, &module.id), - get_env_val(CB_CONFIG_ENV, CB_CONFIG_NAME), + get_env_val(CB_CONFIG_ENV, CB_CONFIG_DEFAULT), get_env_val(BUILDER_SERVER_ENV, &builder_events_port.to_string()), ]); - module_envs.extend(logging_envs.clone()); if metrics_enabled { let (key, val) = get_env_uval(METRICS_SERVER_ENV, metrics_port as u64); module_envs.insert(key, val); } + if log_to_file { + let (key, val) = get_env_val(LOGS_DIR_ENV, LOGS_DIR_DEFAULT); + module_envs.insert(key, val); + } // networks let modules_networks = if metrics_enabled { @@ -200,13 +193,16 @@ pub fn handle_docker_init(config_path: String, output_dir: String) -> Result<()> }); } - let mut pbs_envs = IndexMap::from([get_env_val(CB_CONFIG_ENV, CB_CONFIG_NAME)]); - pbs_envs.extend(logging_envs.clone()); + let mut pbs_envs = IndexMap::from([get_env_val(CB_CONFIG_ENV, CB_CONFIG_DEFAULT)]); + if metrics_enabled { let (key, val) = get_env_uval(METRICS_SERVER_ENV, metrics_port as u64); pbs_envs.insert(key, val); } - + if log_to_file { + let (key, val) = get_env_val(LOGS_DIR_ENV, LOGS_DIR_DEFAULT); + pbs_envs.insert(key, val); + } if !builder_events_modules.is_empty() { let env = builder_events_modules.join(","); let (k, v) = get_env_val(BUILDER_SERVER_ENV, &env); @@ -253,15 +249,19 @@ pub fn handle_docker_init(config_path: String, output_dir: String) -> Result<()> } let mut signer_envs = IndexMap::from([ - get_env_val(CB_CONFIG_ENV, CB_CONFIG_NAME), + get_env_val(CB_CONFIG_ENV, CB_CONFIG_DEFAULT), get_env_same(JWTS_ENV), get_env_uval(SIGNER_SERVER_ENV, signer_port as u64), ]); - signer_envs.extend(logging_envs); + if metrics_enabled { let (key, val) = get_env_uval(METRICS_SERVER_ENV, metrics_port as u64); signer_envs.insert(key, val); } + if log_to_file { + let (key, val) = get_env_val(LOGS_DIR_ENV, LOGS_DIR_DEFAULT); + signer_envs.insert(key, val); + } // write jwts to env let jwts_json = serde_json::to_string(&jwts).unwrap().clone(); @@ -273,13 +273,16 @@ pub fn handle_docker_init(config_path: String, output_dir: String) -> Result<()> // TODO: generalize this, different loaders may not need volumes but eg ports match signer_config.loader { SignerLoader::File { key_path } => { - volumes.push(Volumes::Simple(format!("./{}:{}:ro", key_path, SIGNER_KEYS))); - let (k, v) = get_env_val(SIGNER_KEYS_ENV, SIGNER_KEYS); + volumes.push(Volumes::Simple(format!("./{}:{}:ro", key_path, SIGNER_DEFAULT))); + let (k, v) = get_env_val(SIGNER_KEYS_ENV, SIGNER_DEFAULT); signer_envs.insert(k, v); } SignerLoader::ValidatorsDir { keys_path, secrets_path } => { - volumes.push(Volumes::Simple(format!("{}:{}:ro", keys_path, SIGNER_DIR_KEYS))); - let (k, v) = get_env_val(SIGNER_DIR_KEYS_ENV, SIGNER_DIR_KEYS); + volumes.push(Volumes::Simple(format!( + "{}:{}:ro", + keys_path, SIGNER_DIR_KEYS_DEFAULT + ))); + let (k, v) = get_env_val(SIGNER_DIR_KEYS_ENV, SIGNER_DIR_KEYS_DEFAULT); signer_envs.insert(k, v); volumes.push(Volumes::Simple(format!( @@ -513,9 +516,9 @@ fn get_env_uval(k: &str, v: u64) -> (String, Option) { (k.into(), Some(SingleValue::Unsigned(v))) } -fn get_env_bool(k: &str, v: bool) -> (String, Option) { - (k.into(), Some(SingleValue::Bool(v))) -} +// fn get_env_bool(k: &str, v: bool) -> (String, Option) { +// (k.into(), Some(SingleValue::Bool(v))) +// } /// A prometheus target, use to dynamically add targets to the prometheus config #[derive(Debug, Serialize)] @@ -535,7 +538,7 @@ fn get_log_volume(maybe_config: &Option, module_id: &str) -> Optio Volumes::Simple(format!( "{}:{}", p.to_str().expect("could not convert pathbuf to str"), - CB_BASE_LOG_PATH + LOGS_DIR_DEFAULT )) }) } diff --git a/crates/common/src/config/constants.rs b/crates/common/src/config/constants.rs index c2565c56..b0914a13 100644 --- a/crates/common/src/config/constants.rs +++ b/crates/common/src/config/constants.rs @@ -1,30 +1,50 @@ -pub const MODULE_ID_ENV: &str = "CB_MODULE_ID"; -pub const MODULE_JWT_ENV: &str = "CB_SIGNER_JWT"; +///////////////////////// COMMMON ///////////////////////// + +/// Path to the main toml config file +pub const CB_CONFIG_ENV: &str = "CB_CONFIG"; +pub const CB_CONFIG_DEFAULT: &str = "/cb-config.toml"; + +/// Where to receive scrape requests from Prometheus pub const METRICS_SERVER_ENV: &str = "METRICS_SERVER"; -pub const SIGNER_SERVER_ENV: &str = "SIGNER_SERVER"; -pub const BUILDER_SERVER_ENV: &str = "BUILDER_SERVER"; -pub const MAX_LOG_FILES_ENV: &str = "MAX_LOG_FILES"; -pub const RUST_LOG_ENV: &str = "RUST_LOG"; -pub const USE_FILE_LOGS_ENV: &str = "USE_FILE_LOGS"; -pub const CB_BASE_LOG_PATH: &str = "/var/logs/commit-boost"; +/// Path to logs directory +pub const LOGS_DIR_ENV: &str = "CB_LOGS_DIR"; +pub const LOGS_DIR_DEFAULT: &str = "/var/logs/commit-boost"; -pub const CB_CONFIG_ENV: &str = "CB_CONFIG"; -pub const CB_CONFIG_NAME: &str = "/cb-config.toml"; +///////////////////////// PBS ///////////////////////// + +pub const PBS_IMAGE_DEFAULT: &str = "ghcr.io/commit-boost/pbs:latest"; +pub const PBS_MODULE_NAME: &str = "pbs"; + +///////////////////////// SIGNER ///////////////////////// +pub const SIGNER_IMAGE_DEFAULT: &str = "ghcr.io/commit-boost/signer:latest"; +pub const SIGNER_MODULE_NAME: &str = "signer"; + +/// Comma separated list module_id=jwt_secret +pub const JWTS_ENV: &str = "CB_JWTS"; + +/// Path to json file with plaintext keys (testing only) pub const SIGNER_KEYS_ENV: &str = "CB_SIGNER_FILE"; -pub const SIGNER_KEYS: &str = "/keys.json"; +pub const SIGNER_DEFAULT: &str = "/keys.json"; +/// Path to `keys` folder pub const SIGNER_DIR_KEYS_ENV: &str = "SIGNER_LOADER_DIR_KEYS"; -pub const SIGNER_DIR_KEYS: &str = "/keys"; +pub const SIGNER_DIR_KEYS_DEFAULT: &str = "/keys"; +/// Path to `secrets` folder pub const SIGNER_DIR_SECRETS_ENV: &str = "SIGNER_LOADER_DIR_SECRETS"; pub const SIGNER_DIR_SECRETS: &str = "/secrets"; -pub const JWTS_ENV: &str = "CB_JWTS"; +///////////////////////// MODULES ///////////////////////// -// TODO: replace these with an actual image in the registry -pub const PBS_DEFAULT_IMAGE: &str = "ghcr.io/commit-boost/pbs:latest"; -pub const SIGNER_IMAGE: &str = "ghcr.io/commit-boost/signer:latest"; +/// The unique ID of the module +pub const MODULE_ID_ENV: &str = "CB_MODULE_ID"; -// Module names -pub const PBS_MODULE_NAME: &str = "pbs"; -pub const SIGNER_MODULE_NAME: &str = "signer"; +// Commit modules +/// The JWT secret for the module to communicate with the signer module +pub const MODULE_JWT_ENV: &str = "CB_SIGNER_JWT"; +/// Where to send signature request +pub const SIGNER_SERVER_ENV: &str = "SIGNER_SERVER"; + +/// Events modules +/// Where to receive builder events +pub const BUILDER_SERVER_ENV: &str = "BUILDER_SERVER"; diff --git a/crates/common/src/config/log.rs b/crates/common/src/config/log.rs index 774102ef..2e6b2805 100644 --- a/crates/common/src/config/log.rs +++ b/crates/common/src/config/log.rs @@ -1,8 +1,9 @@ use std::path::PathBuf; +use eyre::Result; use serde::{Deserialize, Serialize}; -use super::CB_BASE_LOG_PATH; +use super::{load_optional_env_var, CommitBoostConfig, LOGS_DIR_DEFAULT, LOGS_DIR_ENV}; #[derive(Clone, Debug, Deserialize, Serialize)] pub struct LogsSettings { @@ -14,8 +15,33 @@ pub struct LogsSettings { pub max_log_files: Option, } +impl Default for LogsSettings { + fn default() -> Self { + LogsSettings { + log_dir_path: default_log_dir_path(), + log_level: default_log_level(), + max_log_files: None, + } + } +} + +impl LogsSettings { + pub fn from_env_config() -> Result> { + let mut config = CommitBoostConfig::from_env_path()?; + + // Override log dir path if env var is set + if let Some(log_config) = config.logs.as_mut() { + if let Some(log_dir) = load_optional_env_var(LOGS_DIR_ENV) { + log_config.log_dir_path = log_dir.into(); + } + } + + Ok(config.logs) + } +} + fn default_log_dir_path() -> PathBuf { - CB_BASE_LOG_PATH.into() + LOGS_DIR_DEFAULT.into() } pub fn default_log_level() -> String { diff --git a/crates/common/src/config/pbs.rs b/crates/common/src/config/pbs.rs index ca7dc332..362e25db 100644 --- a/crates/common/src/config/pbs.rs +++ b/crates/common/src/config/pbs.rs @@ -7,7 +7,7 @@ use eyre::Result; use serde::{de::DeserializeOwned, Deserialize, Serialize}; use url::Url; -use super::{constants::PBS_DEFAULT_IMAGE, CommitBoostConfig}; +use super::{constants::PBS_IMAGE_DEFAULT, CommitBoostConfig}; use crate::{ commit::client::SignerClient, config::{load_env_var, load_file_from_env, CB_CONFIG_ENV, MODULE_JWT_ENV, SIGNER_SERVER_ENV}, @@ -101,7 +101,7 @@ pub struct PbsModuleConfig { } fn default_pbs() -> String { - PBS_DEFAULT_IMAGE.to_string() + PBS_IMAGE_DEFAULT.to_string() } /// Loads the default pbs config, i.e. with no signer client or custom data diff --git a/crates/common/src/config/signer.rs b/crates/common/src/config/signer.rs index 0ed3e5fa..c0b1f012 100644 --- a/crates/common/src/config/signer.rs +++ b/crates/common/src/config/signer.rs @@ -3,7 +3,7 @@ use eyre::Result; use serde::{Deserialize, Serialize}; use super::{ - constants::{SIGNER_IMAGE, SIGNER_SERVER_ENV}, + constants::{SIGNER_IMAGE_DEFAULT, SIGNER_SERVER_ENV}, utils::{load_env_var, load_jwts}, CommitBoostConfig, }; @@ -22,7 +22,7 @@ pub struct SignerConfig { } fn default_signer() -> String { - SIGNER_IMAGE.to_string() + SIGNER_IMAGE_DEFAULT.to_string() } #[derive(Debug)] diff --git a/crates/common/src/utils.rs b/crates/common/src/utils.rs index d85e023d..4673f4ff 100644 --- a/crates/common/src/utils.rs +++ b/crates/common/src/utils.rs @@ -1,7 +1,4 @@ -use std::{ - env, - time::{SystemTime, UNIX_EPOCH}, -}; +use std::time::{SystemTime, UNIX_EPOCH}; use alloy::{ primitives::U256, @@ -16,10 +13,7 @@ use tracing_appender::{non_blocking::WorkerGuard, rolling::Rotation}; use tracing_subscriber::{fmt::Layer, prelude::*, EnvFilter}; use crate::{ - config::{ - default_log_level, load_optional_env_var, CB_BASE_LOG_PATH, MAX_LOG_FILES_ENV, - PBS_MODULE_NAME, RUST_LOG_ENV, USE_FILE_LOGS_ENV, - }, + config::{LogsSettings, LOGS_DIR_DEFAULT, PBS_MODULE_NAME}, pbs::HEADER_VERSION_VALUE, types::Chain, }; @@ -123,33 +117,33 @@ pub const fn default_u256() -> U256 { } // LOGGING -pub fn initialize_tracing_log(module_id: &str) -> WorkerGuard { - let level_env = std::env::var(RUST_LOG_ENV).unwrap_or(default_log_level()); +pub fn initialize_tracing_log(module_id: &str) -> eyre::Result { + let settings = LogsSettings::from_env_config()?; + + // Use file logs only if setting is set + let use_file_logs = settings.is_some(); + let settings = settings.unwrap_or_default(); + // Log level for stdout - let stdout_log_level = match level_env.parse::() { + let stdout_log_level = match settings.log_level.parse::() { Ok(f) => f, Err(_) => { - eprintln!("Invalid RUST_LOG value {}, defaulting to info", level_env); + eprintln!("Invalid RUST_LOG value {}, defaulting to info", settings.log_level); Level::INFO } }; let stdout_filter = format_crates_filter(Level::INFO.as_str(), stdout_log_level.as_str()); - let use_file_logs = load_optional_env_var(USE_FILE_LOGS_ENV) - .map(|s| s.parse().expect("failed to parse USE_FILE_LOGS")) - .unwrap_or(false); - if use_file_logs { // Log all events to a rolling log file. let mut builder = tracing_appender::rolling::Builder::new().filename_prefix(module_id.to_lowercase()); - if let Ok(value) = env::var(MAX_LOG_FILES_ENV) { - builder = builder - .max_log_files(value.parse().expect("MAX_LOG_FILES is not a valid usize value")); + if let Some(value) = settings.max_log_files { + builder = builder.max_log_files(value); } let file_appender = builder .rotation(Rotation::DAILY) - .build(CB_BASE_LOG_PATH) + .build(LOGS_DIR_DEFAULT) .expect("failed building rolling file appender"); let (writer, guard) = tracing_appender::non_blocking(file_appender); @@ -169,7 +163,7 @@ pub fn initialize_tracing_log(module_id: &str) -> WorkerGuard { .with_filter(file_log_filter); tracing_subscriber::registry().with(stdout_layer.and_then(file_layer)).init(); - guard + Ok(guard) } else { let (writer, guard) = tracing_appender::non_blocking(std::io::stdout()); let stdout_layer = tracing_subscriber::fmt::layer() @@ -177,11 +171,11 @@ pub fn initialize_tracing_log(module_id: &str) -> WorkerGuard { .with_writer(writer) .with_filter(stdout_filter); tracing_subscriber::registry().with(stdout_layer).init(); - guard + Ok(guard) } } -pub fn initialize_pbs_tracing_log() -> WorkerGuard { +pub fn initialize_pbs_tracing_log() -> eyre::Result { initialize_tracing_log(PBS_MODULE_NAME) } diff --git a/examples/builder_log/Cargo.toml b/examples/builder_log/Cargo.toml index 1a4dae26..cc147db4 100644 --- a/examples/builder_log/Cargo.toml +++ b/examples/builder_log/Cargo.toml @@ -13,3 +13,4 @@ async-trait.workspace = true # telemetry tracing.workspace = true +eyre.workspace = true diff --git a/examples/builder_log/src/main.rs b/examples/builder_log/src/main.rs index 29c00e2f..96544856 100644 --- a/examples/builder_log/src/main.rs +++ b/examples/builder_log/src/main.rs @@ -13,10 +13,10 @@ impl OnBuilderApiEvent for LogProcessor { } #[tokio::main] -async fn main() { +async fn main() -> eyre::Result<()> { match load_builder_module_config::<()>() { Ok(config) => { - let _guard = initialize_tracing_log(&config.id); + let _guard = initialize_tracing_log(&config.id)?; info!(module_id = %config.id, "Starting module"); @@ -30,4 +30,6 @@ async fn main() { eprintln!("Failed to load module config: {err:?}"); } } + + Ok(()) } diff --git a/examples/da_commit/src/main.rs b/examples/da_commit/src/main.rs index 09abcf2c..906dd0e2 100644 --- a/examples/da_commit/src/main.rs +++ b/examples/da_commit/src/main.rs @@ -114,7 +114,7 @@ async fn main() -> Result<()> { match load_commit_module_config::() { Ok(config) => { - let _guard = initialize_tracing_log(&config.id); + let _guard = initialize_tracing_log(&config.id)?; info!( module_id = %config.id, diff --git a/examples/status_api/src/main.rs b/examples/status_api/src/main.rs index 6879c795..58d3b52a 100644 --- a/examples/status_api/src/main.rs +++ b/examples/status_api/src/main.rs @@ -82,7 +82,7 @@ async fn main() -> Result<()> { color_eyre::install()?; let (pbs_config, extra) = load_pbs_custom_config::()?; - let _guard = initialize_pbs_tracing_log(); + let _guard = initialize_pbs_tracing_log()?; let custom_state = MyBuilderState::from_config(extra); let state = PbsState::new(pbs_config).with_data(custom_state); From 989db55af03d9cc39b0e1ff7982a7394e605df0c Mon Sep 17 00:00:00 2001 From: ltitanb Date: Thu, 12 Sep 2024 10:52:52 +0100 Subject: [PATCH 2/6] fix signer envs --- crates/cli/src/docker_init.rs | 6 +++--- crates/common/src/commit/client.rs | 8 ++++---- crates/common/src/config/constants.rs | 5 ++++- crates/common/src/config/module.rs | 4 ++-- crates/common/src/config/pbs.rs | 4 ++-- crates/metrics/src/provider.rs | 3 ++- 6 files changed, 17 insertions(+), 13 deletions(-) diff --git a/crates/cli/src/docker_init.rs b/crates/cli/src/docker_init.rs index 06effb74..92a4c979 100644 --- a/crates/cli/src/docker_init.rs +++ b/crates/cli/src/docker_init.rs @@ -6,7 +6,7 @@ use cb_common::{ CB_CONFIG_ENV, JWTS_ENV, LOGS_DIR_DEFAULT, LOGS_DIR_ENV, METRICS_SERVER_ENV, MODULE_ID_ENV, MODULE_JWT_ENV, PBS_MODULE_NAME, SIGNER_DEFAULT, SIGNER_DIR_KEYS_DEFAULT, SIGNER_DIR_KEYS_ENV, SIGNER_DIR_SECRETS, SIGNER_DIR_SECRETS_ENV, SIGNER_KEYS_ENV, - SIGNER_MODULE_NAME, SIGNER_SERVER_ENV, + SIGNER_MODULE_NAME, SIGNER_PORT_ENV, SIGNER_SERVER_ENV, }, loader::SignerLoader, utils::random_jwt, @@ -56,7 +56,7 @@ pub fn handle_docker_init(config_path: String, output_dir: String) -> Result<()> // address for signer API communication let signer_port = 20000; - let signer_server = format!("cb_signer:{signer_port}"); + let signer_server = format!("http://cb_signer:{signer_port}"); let builder_events_port = 30000; let mut builder_events_modules = Vec::new(); @@ -251,7 +251,7 @@ pub fn handle_docker_init(config_path: String, output_dir: String) -> Result<()> let mut signer_envs = IndexMap::from([ get_env_val(CB_CONFIG_ENV, CB_CONFIG_DEFAULT), get_env_same(JWTS_ENV), - get_env_uval(SIGNER_SERVER_ENV, signer_port as u64), + get_env_uval(SIGNER_PORT_ENV, signer_port as u64), ]); if metrics_enabled { diff --git a/crates/common/src/commit/client.rs b/crates/common/src/commit/client.rs index 284e320c..0433334a 100644 --- a/crates/common/src/commit/client.rs +++ b/crates/common/src/commit/client.rs @@ -4,6 +4,7 @@ use alloy::rpc::types::beacon::BlsSignature; use eyre::WrapErr; use reqwest::header::{HeaderMap, HeaderValue, AUTHORIZATION}; use serde::Deserialize; +use url::Url; use super::{ constants::{GENERATE_PROXY_KEY_PATH, GET_PUBKEYS_PATH, REQUEST_SIGNATURE_PATH}, @@ -25,14 +26,13 @@ use crate::{ #[derive(Debug, Clone)] pub struct SignerClient { /// Url endpoint of the Signer Module - url: Arc, + url: Arc, client: reqwest::Client, } impl SignerClient { /// Create a new SignerClient - pub fn new(signer_server_address: String, jwt: &str) -> eyre::Result { - let url = format!("http://{}", signer_server_address); + pub fn new(signer_server_url: Url, jwt: &str) -> eyre::Result { let mut headers = HeaderMap::new(); let mut auth_value = @@ -44,7 +44,7 @@ impl SignerClient { .default_headers(headers) .build()?; - Ok(Self { url: url.into(), client }) + Ok(Self { url: signer_server_url.into(), client }) } /// Request a list of validator pubkeys for which signatures can be diff --git a/crates/common/src/config/constants.rs b/crates/common/src/config/constants.rs index b0914a13..0a1a5722 100644 --- a/crates/common/src/config/constants.rs +++ b/crates/common/src/config/constants.rs @@ -21,6 +21,9 @@ pub const PBS_MODULE_NAME: &str = "pbs"; pub const SIGNER_IMAGE_DEFAULT: &str = "ghcr.io/commit-boost/signer:latest"; pub const SIGNER_MODULE_NAME: &str = "signer"; +/// Where the signer module should open the server +pub const SIGNER_PORT_ENV: &str = "CB_SIGNER_PORT"; + /// Comma separated list module_id=jwt_secret pub const JWTS_ENV: &str = "CB_JWTS"; @@ -43,7 +46,7 @@ pub const MODULE_ID_ENV: &str = "CB_MODULE_ID"; /// The JWT secret for the module to communicate with the signer module pub const MODULE_JWT_ENV: &str = "CB_SIGNER_JWT"; /// Where to send signature request -pub const SIGNER_SERVER_ENV: &str = "SIGNER_SERVER"; +pub const SIGNER_SERVER_ENV: &str = "CB_SIGNER_SERVER"; /// Events modules /// Where to receive builder events diff --git a/crates/common/src/config/module.rs b/crates/common/src/config/module.rs index 43789cd8..635879b0 100644 --- a/crates/common/src/config/module.rs +++ b/crates/common/src/config/module.rs @@ -60,7 +60,7 @@ pub struct StartCommitModuleConfig { pub fn load_commit_module_config() -> Result> { let module_id = ModuleId(load_env_var(MODULE_ID_ENV)?); let module_jwt = Jwt(load_env_var(MODULE_JWT_ENV)?); - let signer_server_address = load_env_var(SIGNER_SERVER_ENV)?; + let signer_server_url = load_env_var(SIGNER_SERVER_ENV)?.parse()?; #[derive(Debug, Deserialize)] struct ThisModuleConfig { @@ -104,7 +104,7 @@ pub fn load_commit_module_config() -> Result() -> Result<(PbsModuleConfig, let signer_client = if cb_config.pbs.static_config.with_signer { // if custom pbs requires a signer client, load jwt let module_jwt = load_env_var(MODULE_JWT_ENV)?; - let signer_server_address = load_env_var(SIGNER_SERVER_ENV)?; - Some(SignerClient::new(signer_server_address, &module_jwt)?) + let signer_server_url = load_env_var(SIGNER_SERVER_ENV)?.parse()?; + Some(SignerClient::new(signer_server_url, &module_jwt)?) } else { None }; diff --git a/crates/metrics/src/provider.rs b/crates/metrics/src/provider.rs index 39852a0d..97b2d063 100644 --- a/crates/metrics/src/provider.rs +++ b/crates/metrics/src/provider.rs @@ -8,6 +8,7 @@ use axum::{ routing::get, }; use cb_common::config::ModuleMetricsConfig; +use eyre::bail; use prometheus::{Encoder, Registry, TextEncoder}; use tokio::net::TcpListener; use tracing::{error, info, trace, warn}; @@ -52,7 +53,7 @@ impl MetricsProvider { axum::serve(listener, router).await?; - Err(eyre::eyre!("Metrics server stopped")) + bail!("Metrics server stopped") } } From 668c0758813c9c3ebbc475281bbffd2225600916 Mon Sep 17 00:00:00 2001 From: ltitanb Date: Thu, 12 Sep 2024 13:27:16 +0100 Subject: [PATCH 3/6] signer envs + renaming --- crates/cli/src/docker_init.rs | 46 +++++++++++++++------------ crates/common/src/config/constants.rs | 13 +++++--- crates/common/src/config/metrics.rs | 4 +-- crates/common/src/config/mod.rs | 2 +- crates/common/src/config/module.rs | 12 +++---- crates/common/src/config/pbs.rs | 6 ++-- crates/common/src/config/signer.rs | 4 +-- crates/common/src/config/utils.rs | 33 +++++++++++++++++-- crates/common/src/pbs/event.rs | 4 +-- 9 files changed, 81 insertions(+), 43 deletions(-) diff --git a/crates/cli/src/docker_init.rs b/crates/cli/src/docker_init.rs index 92a4c979..8e1c6a76 100644 --- a/crates/cli/src/docker_init.rs +++ b/crates/cli/src/docker_init.rs @@ -2,13 +2,14 @@ use std::{path::Path, vec}; use cb_common::{ config::{ - CommitBoostConfig, LogsSettings, ModuleKind, BUILDER_SERVER_ENV, CB_CONFIG_DEFAULT, - CB_CONFIG_ENV, JWTS_ENV, LOGS_DIR_DEFAULT, LOGS_DIR_ENV, METRICS_SERVER_ENV, MODULE_ID_ENV, - MODULE_JWT_ENV, PBS_MODULE_NAME, SIGNER_DEFAULT, SIGNER_DIR_KEYS_DEFAULT, + CommitBoostConfig, LogsSettings, ModuleKind, BUILDER_PORT_ENV, BUILDER_URLS_ENV, + CONFIG_DEFAULT, CONFIG_ENV, JWTS_ENV, LOGS_DIR_DEFAULT, LOGS_DIR_ENV, METRICS_PORT_ENV, + MODULE_ID_ENV, MODULE_JWT_ENV, PBS_MODULE_NAME, SIGNER_DEFAULT, SIGNER_DIR_KEYS_DEFAULT, SIGNER_DIR_KEYS_ENV, SIGNER_DIR_SECRETS, SIGNER_DIR_SECRETS_ENV, SIGNER_KEYS_ENV, - SIGNER_MODULE_NAME, SIGNER_PORT_ENV, SIGNER_SERVER_ENV, + SIGNER_MODULE_NAME, SIGNER_PORT_ENV, SIGNER_URL_ENV, }, loader::SignerLoader, + types::ModuleId, utils::random_jwt, }; use docker_compose_types::{ @@ -44,7 +45,7 @@ pub fn handle_docker_init(config_path: String, output_dir: String) -> Result<()> let mut volumes = IndexMap::new(); // config volume to pass to all services - let config_volume = Volumes::Simple(format!("./{}:{}:ro", config_path, CB_CONFIG_DEFAULT)); + let config_volume = Volumes::Simple(format!("./{}:{}:ro", config_path, CONFIG_DEFAULT)); let mut jwts = IndexMap::new(); // envs to write in .env file @@ -89,9 +90,9 @@ pub fn handle_docker_init(config_path: String, output_dir: String) -> Result<()> // module ids are assumed unique, so envs dont override each other let mut module_envs = IndexMap::from([ get_env_val(MODULE_ID_ENV, &module.id), - get_env_val(CB_CONFIG_ENV, CB_CONFIG_DEFAULT), + get_env_val(CONFIG_ENV, CONFIG_DEFAULT), get_env_interp(MODULE_JWT_ENV, &jwt_name), - get_env_val(SIGNER_SERVER_ENV, &signer_server), + get_env_val(SIGNER_URL_ENV, &signer_server), ]); // Pass on the env variables @@ -105,7 +106,7 @@ pub fn handle_docker_init(config_path: String, output_dir: String) -> Result<()> let env_file = module.env_file.map(EnvFile::Simple); if metrics_enabled { - let (key, val) = get_env_uval(METRICS_SERVER_ENV, metrics_port as u64); + let (key, val) = get_env_uval(METRICS_PORT_ENV, metrics_port as u64); module_envs.insert(key, val); } if log_to_file { @@ -140,17 +141,18 @@ pub fn handle_docker_init(config_path: String, output_dir: String) -> Result<()> } // an event module just needs a port to listen on ModuleKind::Events => { - builder_events_modules.push(format!("{module_cid}:{builder_events_port}")); + builder_events_modules + .push(format!("http://{module_cid}:{builder_events_port}")); // module ids are assumed unique, so envs dont override each other let mut module_envs = IndexMap::from([ get_env_val(MODULE_ID_ENV, &module.id), - get_env_val(CB_CONFIG_ENV, CB_CONFIG_DEFAULT), - get_env_val(BUILDER_SERVER_ENV, &builder_events_port.to_string()), + get_env_val(CONFIG_ENV, CONFIG_DEFAULT), + get_env_uval(BUILDER_PORT_ENV, builder_events_port), ]); if metrics_enabled { - let (key, val) = get_env_uval(METRICS_SERVER_ENV, metrics_port as u64); + let (key, val) = get_env_uval(METRICS_PORT_ENV, metrics_port as u64); module_envs.insert(key, val); } if log_to_file { @@ -193,10 +195,10 @@ pub fn handle_docker_init(config_path: String, output_dir: String) -> Result<()> }); } - let mut pbs_envs = IndexMap::from([get_env_val(CB_CONFIG_ENV, CB_CONFIG_DEFAULT)]); + let mut pbs_envs = IndexMap::from([get_env_val(CONFIG_ENV, CONFIG_DEFAULT)]); if metrics_enabled { - let (key, val) = get_env_uval(METRICS_SERVER_ENV, metrics_port as u64); + let (key, val) = get_env_uval(METRICS_PORT_ENV, metrics_port as u64); pbs_envs.insert(key, val); } if log_to_file { @@ -205,7 +207,7 @@ pub fn handle_docker_init(config_path: String, output_dir: String) -> Result<()> } if !builder_events_modules.is_empty() { let env = builder_events_modules.join(","); - let (k, v) = get_env_val(BUILDER_SERVER_ENV, &env); + let (k, v) = get_env_val(BUILDER_URLS_ENV, &env); pbs_envs.insert(k, v); } @@ -249,13 +251,13 @@ pub fn handle_docker_init(config_path: String, output_dir: String) -> Result<()> } let mut signer_envs = IndexMap::from([ - get_env_val(CB_CONFIG_ENV, CB_CONFIG_DEFAULT), + get_env_val(CONFIG_ENV, CONFIG_DEFAULT), get_env_same(JWTS_ENV), get_env_uval(SIGNER_PORT_ENV, signer_port as u64), ]); if metrics_enabled { - let (key, val) = get_env_uval(METRICS_SERVER_ENV, metrics_port as u64); + let (key, val) = get_env_uval(METRICS_PORT_ENV, metrics_port as u64); signer_envs.insert(key, val); } if log_to_file { @@ -264,8 +266,7 @@ pub fn handle_docker_init(config_path: String, output_dir: String) -> Result<()> } // write jwts to env - let jwts_json = serde_json::to_string(&jwts).unwrap().clone(); - envs.insert(JWTS_ENV.into(), format!("{jwts_json:?}")); + envs.insert(JWTS_ENV.into(), format_comma_separated(&jwts)); // volumes let mut volumes = vec![config_volume.clone()]; @@ -534,7 +535,7 @@ struct PrometheusLabelsConfig { fn get_log_volume(maybe_config: &Option, module_id: &str) -> Option { maybe_config.as_ref().map(|config| { - let p = config.log_dir_path.join(module_id); + let p = config.log_dir_path.join(module_id.to_lowercase()); Volumes::Simple(format!( "{}:{}", p.to_str().expect("could not convert pathbuf to str"), @@ -542,3 +543,8 @@ fn get_log_volume(maybe_config: &Option, module_id: &str) -> Optio )) }) } + +/// Formats as a comma separated list of key=value +fn format_comma_separated(map: &IndexMap) -> String { + map.iter().map(|(k, v)| format!("{}={}", k.to_string(), v)).collect::>().join(",") +} diff --git a/crates/common/src/config/constants.rs b/crates/common/src/config/constants.rs index 0a1a5722..8b9cc640 100644 --- a/crates/common/src/config/constants.rs +++ b/crates/common/src/config/constants.rs @@ -1,11 +1,11 @@ ///////////////////////// COMMMON ///////////////////////// /// Path to the main toml config file -pub const CB_CONFIG_ENV: &str = "CB_CONFIG"; -pub const CB_CONFIG_DEFAULT: &str = "/cb-config.toml"; +pub const CONFIG_ENV: &str = "CB_CONFIG"; +pub const CONFIG_DEFAULT: &str = "/cb-config.toml"; /// Where to receive scrape requests from Prometheus -pub const METRICS_SERVER_ENV: &str = "METRICS_SERVER"; +pub const METRICS_PORT_ENV: &str = "CB_METRICS_PORT"; /// Path to logs directory pub const LOGS_DIR_ENV: &str = "CB_LOGS_DIR"; @@ -16,6 +16,9 @@ pub const LOGS_DIR_DEFAULT: &str = "/var/logs/commit-boost"; pub const PBS_IMAGE_DEFAULT: &str = "ghcr.io/commit-boost/pbs:latest"; pub const PBS_MODULE_NAME: &str = "pbs"; +/// Urls the pbs modules should post events to (comma separated) +pub const BUILDER_URLS_ENV: &str = "CB_BUILDER_URLS"; + ///////////////////////// SIGNER ///////////////////////// pub const SIGNER_IMAGE_DEFAULT: &str = "ghcr.io/commit-boost/signer:latest"; @@ -46,8 +49,8 @@ pub const MODULE_ID_ENV: &str = "CB_MODULE_ID"; /// The JWT secret for the module to communicate with the signer module pub const MODULE_JWT_ENV: &str = "CB_SIGNER_JWT"; /// Where to send signature request -pub const SIGNER_SERVER_ENV: &str = "CB_SIGNER_SERVER"; +pub const SIGNER_URL_ENV: &str = "CB_SIGNER_URL"; /// Events modules /// Where to receive builder events -pub const BUILDER_SERVER_ENV: &str = "BUILDER_SERVER"; +pub const BUILDER_PORT_ENV: &str = "CB_BUILDER_PORT"; diff --git a/crates/common/src/config/metrics.rs b/crates/common/src/config/metrics.rs index a39ce063..264c45b1 100644 --- a/crates/common/src/config/metrics.rs +++ b/crates/common/src/config/metrics.rs @@ -1,7 +1,7 @@ use eyre::Result; use serde::{Deserialize, Serialize}; -use super::{constants::METRICS_SERVER_ENV, load_optional_env_var}; +use super::{constants::METRICS_PORT_ENV, load_optional_env_var}; use crate::utils::default_bool; #[derive(Debug, Serialize, Deserialize, Clone)] @@ -24,7 +24,7 @@ pub struct ModuleMetricsConfig { impl ModuleMetricsConfig { pub fn load_from_env() -> Result> { - if let Some(server_port) = load_optional_env_var(METRICS_SERVER_ENV) { + if let Some(server_port) = load_optional_env_var(METRICS_PORT_ENV) { Ok(Some(ModuleMetricsConfig { server_port: server_port.parse()? })) } else { Ok(None) diff --git a/crates/common/src/config/mod.rs b/crates/common/src/config/mod.rs index a5ad60a4..0205f451 100644 --- a/crates/common/src/config/mod.rs +++ b/crates/common/src/config/mod.rs @@ -46,7 +46,7 @@ impl CommitBoostConfig { } pub fn from_env_path() -> Result { - let config: Self = load_file_from_env(CB_CONFIG_ENV)?; + let config: Self = load_file_from_env(CONFIG_ENV)?; config.validate()?; Ok(config) } diff --git a/crates/common/src/config/module.rs b/crates/common/src/config/module.rs index 635879b0..2476079b 100644 --- a/crates/common/src/config/module.rs +++ b/crates/common/src/config/module.rs @@ -7,10 +7,10 @@ use toml::Table; use crate::{ commit::client::SignerClient, config::{ - constants::{CB_CONFIG_ENV, MODULE_ID_ENV, MODULE_JWT_ENV, SIGNER_SERVER_ENV}, + constants::{CONFIG_ENV, MODULE_ID_ENV, MODULE_JWT_ENV, SIGNER_URL_ENV}, load_env_var, utils::load_file_from_env, - BUILDER_SERVER_ENV, + BUILDER_PORT_ENV, }, types::{Chain, Jwt, ModuleId}, }; @@ -60,7 +60,7 @@ pub struct StartCommitModuleConfig { pub fn load_commit_module_config() -> Result> { let module_id = ModuleId(load_env_var(MODULE_ID_ENV)?); let module_jwt = Jwt(load_env_var(MODULE_JWT_ENV)?); - let signer_server_url = load_env_var(SIGNER_SERVER_ENV)?.parse()?; + let signer_server_url = load_env_var(SIGNER_URL_ENV)?.parse()?; #[derive(Debug, Deserialize)] struct ThisModuleConfig { @@ -85,7 +85,7 @@ pub fn load_commit_module_config() -> Result = load_file_from_env(CB_CONFIG_ENV)?; + let cb_config: StubConfig = load_file_from_env(CONFIG_ENV)?; // find all matching modules config let matches: Vec> = cb_config @@ -129,7 +129,7 @@ pub struct StartBuilderModuleConfig { pub fn load_builder_module_config() -> eyre::Result> { let module_id = ModuleId(load_env_var(MODULE_ID_ENV)?); - let builder_events_port: u16 = load_env_var(BUILDER_SERVER_ENV)?.parse()?; + let builder_events_port: u16 = load_env_var(BUILDER_PORT_ENV)?.parse()?; #[derive(Debug, Deserialize)] struct ThisModuleConfig { @@ -154,7 +154,7 @@ pub fn load_builder_module_config() -> eyre::Result = load_file_from_env(CB_CONFIG_ENV)?; + let cb_config: StubConfig = load_file_from_env(CONFIG_ENV)?; // find all matching modules config let matches: Vec> = cb_config diff --git a/crates/common/src/config/pbs.rs b/crates/common/src/config/pbs.rs index 706e7ca9..90bce76c 100644 --- a/crates/common/src/config/pbs.rs +++ b/crates/common/src/config/pbs.rs @@ -10,7 +10,7 @@ use url::Url; use super::{constants::PBS_IMAGE_DEFAULT, CommitBoostConfig}; use crate::{ commit::client::SignerClient, - config::{load_env_var, load_file_from_env, CB_CONFIG_ENV, MODULE_JWT_ENV, SIGNER_SERVER_ENV}, + config::{load_env_var, load_file_from_env, CONFIG_ENV, MODULE_JWT_ENV, SIGNER_URL_ENV}, pbs::{BuilderEventPublisher, DefaultTimeout, RelayClient, RelayEntry, LATE_IN_SLOT_TIME_MS}, types::Chain, utils::{as_eth_str, default_bool, default_u256, default_u64}, @@ -139,7 +139,7 @@ pub fn load_pbs_custom_config() -> Result<(PbsModuleConfig, } // load module config including the extra data (if any) - let cb_config: StubConfig = load_file_from_env(CB_CONFIG_ENV)?; + let cb_config: StubConfig = load_file_from_env(CONFIG_ENV)?; cb_config.pbs.static_config.pbs_config.validate()?; let relay_clients = @@ -149,7 +149,7 @@ pub fn load_pbs_custom_config() -> Result<(PbsModuleConfig, let signer_client = if cb_config.pbs.static_config.with_signer { // if custom pbs requires a signer client, load jwt let module_jwt = load_env_var(MODULE_JWT_ENV)?; - let signer_server_url = load_env_var(SIGNER_SERVER_ENV)?.parse()?; + let signer_server_url = load_env_var(SIGNER_URL_ENV)?.parse()?; Some(SignerClient::new(signer_server_url, &module_jwt)?) } else { None diff --git a/crates/common/src/config/signer.rs b/crates/common/src/config/signer.rs index c0b1f012..2be2e02e 100644 --- a/crates/common/src/config/signer.rs +++ b/crates/common/src/config/signer.rs @@ -3,7 +3,7 @@ use eyre::Result; use serde::{Deserialize, Serialize}; use super::{ - constants::{SIGNER_IMAGE_DEFAULT, SIGNER_SERVER_ENV}, + constants::{SIGNER_IMAGE_DEFAULT, SIGNER_URL_ENV}, utils::{load_env_var, load_jwts}, CommitBoostConfig, }; @@ -38,7 +38,7 @@ impl StartSignerConfig { let config = CommitBoostConfig::from_env_path()?; let jwts = load_jwts()?; - let server_port = load_env_var(SIGNER_SERVER_ENV)?.parse()?; + let server_port = load_env_var(SIGNER_URL_ENV)?.parse()?; Ok(StartSignerConfig { chain: config.chain, diff --git a/crates/common/src/config/utils.rs b/crates/common/src/config/utils.rs index 5f1be93f..c056f26e 100644 --- a/crates/common/src/config/utils.rs +++ b/crates/common/src/config/utils.rs @@ -1,5 +1,5 @@ use bimap::BiHashMap; -use eyre::{Context, Result}; +use eyre::{bail, Context, Ok, Result}; use serde::de::DeserializeOwned; use super::constants::JWTS_ENV; @@ -26,5 +26,34 @@ pub fn load_file_from_env(env: &str) -> Result { /// Loads a bidirectional map of module id <-> jwt token from a json env pub fn load_jwts() -> Result> { let jwts = std::env::var(JWTS_ENV).wrap_err(format!("{JWTS_ENV} is not set"))?; - serde_json::from_str(&jwts).wrap_err("could not deserialize json from string") + decode_string_to_map(&jwts) +} + +fn decode_string_to_map(raw: &str) -> Result> { + // trim the string and split for comma + raw.trim() + .split(',') + .map(|pair| { + let mut parts = pair.trim().split('='); + match (parts.next(), parts.next()) { + (Some(key), Some(value)) => Ok((ModuleId(key.into()), Jwt(value.into()))), + _ => bail!("Invalid key-value pair: {pair}"), + } + }) + .collect() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_decode_string_to_map() { + let raw = " KEY=VALUE , KEY2=value2 "; + + let map = decode_string_to_map(raw).unwrap(); + + assert_eq!(map.get_by_left(&ModuleId("KEY".into())), Some(&Jwt("VALUE".into()))); + assert_eq!(map.get_by_left(&ModuleId("KEY2".into())), Some(&Jwt("value2".into()))); + } } diff --git a/crates/common/src/pbs/event.rs b/crates/common/src/pbs/event.rs index 4e176558..513d0aa5 100644 --- a/crates/common/src/pbs/event.rs +++ b/crates/common/src/pbs/event.rs @@ -18,7 +18,7 @@ use super::{ GetHeaderParams, GetHeaderResponse, SignedBlindedBeaconBlock, SubmitBlindedBlockResponse, }; use crate::{ - config::{load_env_var, BUILDER_SERVER_ENV}, + config::{load_env_var, BUILDER_PORT_ENV}, pbs::BUILDER_EVENTS_PATH, }; @@ -47,7 +47,7 @@ impl BuilderEventPublisher { } pub fn new_from_env() -> Option { - load_env_var(BUILDER_SERVER_ENV) + load_env_var(BUILDER_PORT_ENV) .map(|joined| { let endpoints = joined .split(',') From b6e9157522a836f8095ea787b295aaf2cd1c08e0 Mon Sep 17 00:00:00 2001 From: ltitanb Date: Thu, 12 Sep 2024 15:16:14 +0100 Subject: [PATCH 4/6] update docs --- crates/common/src/config/constants.rs | 6 +- docs/docs/architecture/_category_.json | 7 --- docs/docs/architecture/overview.md | 2 +- docs/docs/developing/_category_.json | 7 --- docs/docs/get_started/_category_.json | 7 --- docs/docs/get_started/configuration.md | 2 +- docs/docs/get_started/overview.md | 42 +++++++++----- docs/docs/get_started/running/binary.md | 56 +++++++++++++++++++ .../{running.md => running/docker.md} | 6 +- docs/docs/get_started/troubleshooting.md | 2 +- docs/docs/intro.md | 3 +- docs/sidebars.js | 54 +++++++++++++++++- 12 files changed, 149 insertions(+), 45 deletions(-) delete mode 100644 docs/docs/architecture/_category_.json delete mode 100644 docs/docs/developing/_category_.json delete mode 100644 docs/docs/get_started/_category_.json create mode 100644 docs/docs/get_started/running/binary.md rename docs/docs/get_started/{running.md => running/docker.md} (84%) diff --git a/crates/common/src/config/constants.rs b/crates/common/src/config/constants.rs index 8b9cc640..4db80013 100644 --- a/crates/common/src/config/constants.rs +++ b/crates/common/src/config/constants.rs @@ -31,13 +31,13 @@ pub const SIGNER_PORT_ENV: &str = "CB_SIGNER_PORT"; pub const JWTS_ENV: &str = "CB_JWTS"; /// Path to json file with plaintext keys (testing only) -pub const SIGNER_KEYS_ENV: &str = "CB_SIGNER_FILE"; +pub const SIGNER_KEYS_ENV: &str = "CB_SIGNER_LOADER_FILE"; pub const SIGNER_DEFAULT: &str = "/keys.json"; /// Path to `keys` folder -pub const SIGNER_DIR_KEYS_ENV: &str = "SIGNER_LOADER_DIR_KEYS"; +pub const SIGNER_DIR_KEYS_ENV: &str = "CB_SIGNER_LOADER_KEYS_DIR"; pub const SIGNER_DIR_KEYS_DEFAULT: &str = "/keys"; /// Path to `secrets` folder -pub const SIGNER_DIR_SECRETS_ENV: &str = "SIGNER_LOADER_DIR_SECRETS"; +pub const SIGNER_DIR_SECRETS_ENV: &str = "CB_SIGNER_LOADER_SECRETS_DIR"; pub const SIGNER_DIR_SECRETS: &str = "/secrets"; ///////////////////////// MODULES ///////////////////////// diff --git a/docs/docs/architecture/_category_.json b/docs/docs/architecture/_category_.json deleted file mode 100644 index 9e51a2fc..00000000 --- a/docs/docs/architecture/_category_.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "label": "Architecture", - "position": 5, - "link": { - "type": "generated-index" - } -} \ No newline at end of file diff --git a/docs/docs/architecture/overview.md b/docs/docs/architecture/overview.md index e967a9c9..20137675 100644 --- a/docs/docs/architecture/overview.md +++ b/docs/docs/architecture/overview.md @@ -1,5 +1,5 @@ --- -sidebar_position: 1 +description: Overview of the architecture of Commit-Boost --- # Overview diff --git a/docs/docs/developing/_category_.json b/docs/docs/developing/_category_.json deleted file mode 100644 index 36d2961b..00000000 --- a/docs/docs/developing/_category_.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "label": "Developing", - "position": 4, - "link": { - "type": "generated-index" - } -} \ No newline at end of file diff --git a/docs/docs/get_started/_category_.json b/docs/docs/get_started/_category_.json deleted file mode 100644 index 580c8261..00000000 --- a/docs/docs/get_started/_category_.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "label": "Get Started", - "position": 3, - "link": { - "type": "generated-index" - } -} \ No newline at end of file diff --git a/docs/docs/get_started/configuration.md b/docs/docs/get_started/configuration.md index 6696c2f4..cdab22a7 100644 --- a/docs/docs/get_started/configuration.md +++ b/docs/docs/get_started/configuration.md @@ -1,5 +1,5 @@ --- -sidebar_position: 2 +description: Configure Commit-Boost --- # Configuration diff --git a/docs/docs/get_started/overview.md b/docs/docs/get_started/overview.md index df741a95..403a7c51 100644 --- a/docs/docs/get_started/overview.md +++ b/docs/docs/get_started/overview.md @@ -1,5 +1,5 @@ --- -sidebar_position: 1 +description: Initial setup --- # Overview @@ -17,10 +17,12 @@ Commit-Boost ships with two core modules: - a signer module, which implements the [Signer API](/api) and provides the interface for modules to request proposer commitments ## Setup -Requirements: -- Docker Engine up and running -### Binaries +The Commit-Boost CLI creates a dynamic `docker-compose` file, with services and ports already set up. Alternatively, you can also run each module natively without using Docker. + +Either way, you can compile from source from our repo, or download binaries and fetch docker images from the official releases. + +### Binaries and images Find the latest releases at https://github.com/Commit-Boost/commit-boost-client/releases. The modules are also published at [each release](https://github.com/orgs/Commit-Boost/packages?repo_name=commit-boost-client). @@ -33,15 +35,22 @@ Requirements: run `rustup update` to update Rust and Cargo to the latest version ::: -### Build CLI - ```bash # Pull the repo git clone https://github.com/Commit-Boost/commit-boost-client # Stable branch has the latest released version git checkout stable +``` +:::note +If you get an `openssl` related error try running: `apt-get update && apt-get install -y openssl ca-certificates libssl3 libssl-dev` +::: + +#### Docker +You can now build the CLI: + +```bash # Build the CLI cargo build --release --bin commit-boost @@ -49,13 +58,7 @@ cargo build --release --bin commit-boost ./target/release/commit-boost --version ``` -:::note -If you get an `openssl` related error try running: `apt-get update && apt-get install -y openssl ca-certificates libssl3 libssl-dev` -::: - - -### Modules -You can build modules with the following script: +and the modules as Docker images ```bash bash scripts/build_local_images.sh ``` @@ -65,3 +68,16 @@ If you require `sudo` access to run Docker, you will need `sudo` to run some of ::: This will create two local images called `commitboost_pbs_default` and `commitboost_signer` for the Pbs and Signer module respectively. Make sure to use these images in the `docker_image` field in the `[pbs]` and `[signer]` sections of the `.toml` config file, respectively. + +#### Binaries + +Alternatively, you can also build the modules from source and run them without Docker, in which case you wouldn't need the CLI: + +```bash +# Build the PBS module +cargo build --release --bin default-pbs + +# Build the Signer module +cargo build --release --bin signer-module +``` + diff --git a/docs/docs/get_started/running/binary.md b/docs/docs/get_started/running/binary.md new file mode 100644 index 00000000..7ec6c2a5 --- /dev/null +++ b/docs/docs/get_started/running/binary.md @@ -0,0 +1,56 @@ +--- +description: Run Commit-Boost modules natively +--- + +# Binary +It is also possible to run the native modules without using docker. + +:::warning +Running the modules natively means you opt out of the security guarantees made by Docker and it's up to you how to setup and ensure the modules run safely +::: + + +## Setup +Get the binary of the module either by compiling from source or by downloading a [published release](https://github.com/Commit-Boost/commit-boost-client/releases). + +Modules need some environment variables to work correctly. Here is the complete list + +### Common +- `CB_CONFIG`: required, path to the `toml` config file +- `CB_METRICS_PORT`: optional, port where to expose the `/metrics` endpoint for Prometheus +- `CB_LOGS_DIR`: optional, directory to store logs. This will override the directory in the `toml` config + +### PBS Module +- `CB_BUILDER_URLS`: optional, comma-separated list of urls to `events` modules where to post builder events + +### Signer Module +- `CB_JWTS`: required, comma-separated list of `MODULE_ID=JWT` to process signature requests +- `CB_SIGNER_PORT`: required, port to open the signer server on +For loading keys we currently support: + - `CB_SIGNER_LOADER_FILE`: path to a `.json` with plaintext keys (for testing purposes only) + - `CB_SIGNER_LOADER_KEYS_DIR` and `CB_SIGNER_LOADER_SECRETS_DIR`: paths to the `keys` and `secrets` directories (ERC-2335 style keystores as used in Lighthouse) + + +### Modules +- `CB_MODULE_ID`: required, unique id of the module + +#### Commit modules +- `CB_SIGNER_URL`: requred, url to the signer module server +- `CB_SIGNER_JWT`: required, jwt to use to for signature requests (needs to match what is in `CB_JWTS`) + +#### Events modules +- `CB_BUILDER_PORT`: required, port to open to receive builder events from the PBS module + +Modules might also have additional envs required, which should be detailed by the maintainers. + +## Start + +After creating the `cb-config.toml` file, you need to setup the required envs and run the binary. For example: + +```bash +CB_CONFIG=./cb-config.toml commit-boost-pbs +``` + +## Security +Running the modules natively means you opt out of the security guarantees made by Docker and it's up to you how to setup and ensure the modules run safely. + diff --git a/docs/docs/get_started/running.md b/docs/docs/get_started/running/docker.md similarity index 84% rename from docs/docs/get_started/running.md rename to docs/docs/get_started/running/docker.md index b160dd22..e0dd28e3 100644 --- a/docs/docs/get_started/running.md +++ b/docs/docs/get_started/running/docker.md @@ -1,9 +1,9 @@ --- -sidebar_position: 3 +description: Run Commit-Boost with Docker --- -# Running -Here are the commands currently supported by the CLI. +# Docker +The `commit-boost` cli will generate a dynamic `docker-compose.yml` file using the provided `toml` config file. This is the recommended approach as Docker provides sandboxing of the containers from the rest of your system. ## Init diff --git a/docs/docs/get_started/troubleshooting.md b/docs/docs/get_started/troubleshooting.md index 9140a144..9d8b6456 100644 --- a/docs/docs/get_started/troubleshooting.md +++ b/docs/docs/get_started/troubleshooting.md @@ -1,5 +1,5 @@ --- -sidebar_position: 4 +description: Common issues --- # Troubleshooting diff --git a/docs/docs/intro.md b/docs/docs/intro.md index 3f81fa95..dd77731d 100644 --- a/docs/docs/intro.md +++ b/docs/docs/intro.md @@ -1,6 +1,7 @@ --- -slug: / +id: introduction sidebar_position: 1 +slug: / --- # Introduction diff --git a/docs/sidebars.js b/docs/sidebars.js index 200825fd..0ec40fae 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -14,7 +14,59 @@ /** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ const sidebars = { // By default, Docusaurus generates a sidebar from the docs folder structure - tutorialSidebar: [{ type: 'autogenerated', dirName: '.' }], + // tutorialSidebar: [{ type: 'autogenerated', dirName: '.' }], + + + tutorialSidebar: [ + 'introduction', + 'overview', + { + type: 'category', + label: 'Get started', + link: { + type: 'generated-index', + }, + collapsed: false, + items: [ + 'get_started/overview', + 'get_started/configuration', + { + type: 'category', + label: 'Running', + link: { + type: 'generated-index', + }, + items: [ + 'get_started/running/docker', + 'get_started/running/binary', + + ], + }, + 'get_started/troubleshooting', + ], + }, + { + type: 'category', + label: 'Developing', + link: { + type: 'generated-index', + }, + items: [ + 'developing/custom-modules', + 'developing/commit-module', + ], + }, + { + type: 'category', + label: 'Architecture', + link: { + type: 'generated-index', + }, + items: [ + 'architecture/overview', + ], + }, + ], // But you can create a sidebar manually /* From 5a3bd8ffe0b1035aaaf3c2e8cd8d51edeaf718d7 Mon Sep 17 00:00:00 2001 From: ltitanb Date: Thu, 12 Sep 2024 15:20:49 +0100 Subject: [PATCH 5/6] clippy --- crates/cli/src/docker_init.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/cli/src/docker_init.rs b/crates/cli/src/docker_init.rs index 8e1c6a76..d2d9d9fa 100644 --- a/crates/cli/src/docker_init.rs +++ b/crates/cli/src/docker_init.rs @@ -546,5 +546,5 @@ fn get_log_volume(maybe_config: &Option, module_id: &str) -> Optio /// Formats as a comma separated list of key=value fn format_comma_separated(map: &IndexMap) -> String { - map.iter().map(|(k, v)| format!("{}={}", k.to_string(), v)).collect::>().join(",") + map.iter().map(|(k, v)| format!("{}={}", k, v)).collect::>().join(",") } From 310e346321c2bb9bd98f525961e347e1a80105cf Mon Sep 17 00:00:00 2001 From: ltitanb Date: Fri, 13 Sep 2024 11:25:47 +0100 Subject: [PATCH 6/6] fixes --- crates/common/src/commit/client.rs | 11 ++++++----- crates/common/src/commit/error.rs | 3 +++ crates/common/src/config/pbs.rs | 4 ++-- crates/common/src/config/signer.rs | 6 +++--- crates/common/src/pbs/event.rs | 23 ++++++++++++++--------- 5 files changed, 28 insertions(+), 19 deletions(-) diff --git a/crates/common/src/commit/client.rs b/crates/common/src/commit/client.rs index 0433334a..6f8cb753 100644 --- a/crates/common/src/commit/client.rs +++ b/crates/common/src/commit/client.rs @@ -51,7 +51,8 @@ impl SignerClient { /// requested. // TODO: add more docs on how proxy keys work pub async fn get_pubkeys(&self) -> Result { - let res = self.client.get(format!("{}{}", self.url, GET_PUBKEYS_PATH)).send().await?; + let url = self.url.join(GET_PUBKEYS_PATH)?; + let res = self.client.get(url).send().await?; if !res.status().is_success() { return Err(SignerClientError::FailedRequest { @@ -68,8 +69,8 @@ impl SignerClient { where T: for<'de> Deserialize<'de>, { - let url = format!("{}{}", self.url, REQUEST_SIGNATURE_PATH); - let res = self.client.post(&url).json(&request).send().await?; + let url = self.url.join(REQUEST_SIGNATURE_PATH)?; + let res = self.client.post(url).json(&request).send().await?; let status = res.status(); let response_bytes = res.bytes().await?; @@ -114,8 +115,8 @@ impl SignerClient { where T: PublicKey + for<'de> Deserialize<'de>, { - let url = format!("{}{}", self.url, GENERATE_PROXY_KEY_PATH); - let res = self.client.post(&url).json(&request).send().await?; + let url = self.url.join(GENERATE_PROXY_KEY_PATH)?; + let res = self.client.post(url).json(&request).send().await?; let status = res.status(); let response_bytes = res.bytes().await?; diff --git a/crates/common/src/commit/error.rs b/crates/common/src/commit/error.rs index 1315b82c..94a15aad 100644 --- a/crates/common/src/commit/error.rs +++ b/crates/common/src/commit/error.rs @@ -11,4 +11,7 @@ pub enum SignerClientError { #[error("serde decode error: {0}")] SerdeDecodeError(#[from] serde_json::Error), + + #[error("url parse error: {0}")] + ParseError(#[from] url::ParseError), } diff --git a/crates/common/src/config/pbs.rs b/crates/common/src/config/pbs.rs index 90bce76c..e3bcaaa0 100644 --- a/crates/common/src/config/pbs.rs +++ b/crates/common/src/config/pbs.rs @@ -110,7 +110,7 @@ pub fn load_pbs_config() -> Result { let relay_clients = config.relays.into_iter().map(RelayClient::new).collect::>>()?; - let maybe_publiher = BuilderEventPublisher::new_from_env(); + let maybe_publiher = BuilderEventPublisher::new_from_env()?; Ok(PbsModuleConfig { chain: config.chain, @@ -144,7 +144,7 @@ pub fn load_pbs_custom_config() -> Result<(PbsModuleConfig, let relay_clients = cb_config.relays.into_iter().map(RelayClient::new).collect::>>()?; - let maybe_publiher = BuilderEventPublisher::new_from_env(); + let maybe_publiher = BuilderEventPublisher::new_from_env()?; let signer_client = if cb_config.pbs.static_config.with_signer { // if custom pbs requires a signer client, load jwt diff --git a/crates/common/src/config/signer.rs b/crates/common/src/config/signer.rs index 2be2e02e..99f31db5 100644 --- a/crates/common/src/config/signer.rs +++ b/crates/common/src/config/signer.rs @@ -3,9 +3,9 @@ use eyre::Result; use serde::{Deserialize, Serialize}; use super::{ - constants::{SIGNER_IMAGE_DEFAULT, SIGNER_URL_ENV}, + constants::SIGNER_IMAGE_DEFAULT, utils::{load_env_var, load_jwts}, - CommitBoostConfig, + CommitBoostConfig, SIGNER_PORT_ENV, }; use crate::{ loader::SignerLoader, @@ -38,7 +38,7 @@ impl StartSignerConfig { let config = CommitBoostConfig::from_env_path()?; let jwts = load_jwts()?; - let server_port = load_env_var(SIGNER_URL_ENV)?.parse()?; + let server_port = load_env_var(SIGNER_PORT_ENV)?.parse()?; Ok(StartSignerConfig { chain: config.chain, diff --git a/crates/common/src/pbs/event.rs b/crates/common/src/pbs/event.rs index 513d0aa5..043f8df9 100644 --- a/crates/common/src/pbs/event.rs +++ b/crates/common/src/pbs/event.rs @@ -13,12 +13,13 @@ use reqwest::StatusCode; use serde::{Deserialize, Serialize}; use tokio::net::TcpListener; use tracing::{error, info, trace}; +use url::Url; use super::{ GetHeaderParams, GetHeaderResponse, SignedBlindedBeaconBlock, SubmitBlindedBlockResponse, }; use crate::{ - config::{load_env_var, BUILDER_PORT_ENV}, + config::{load_optional_env_var, BUILDER_URLS_ENV}, pbs::BUILDER_EVENTS_PATH, }; @@ -38,25 +39,29 @@ pub enum BuilderEvent { #[derive(Debug, Clone)] pub struct BuilderEventPublisher { client: reqwest::Client, - endpoints: Vec, + endpoints: Vec, } impl BuilderEventPublisher { - pub fn new(endpoints: Vec) -> Self { + pub fn new(endpoints: Vec) -> Self { Self { client: reqwest::Client::new(), endpoints } } - pub fn new_from_env() -> Option { - load_env_var(BUILDER_PORT_ENV) + pub fn new_from_env() -> eyre::Result> { + load_optional_env_var(BUILDER_URLS_ENV) .map(|joined| { let endpoints = joined + .trim() .split(',') - .map(|s| format!("http://{}{}", s, BUILDER_EVENTS_PATH)) - .collect(); + .map(|base| { + let url = base.trim().parse::()?.join(BUILDER_EVENTS_PATH)?; + Ok(url) + }) + .collect::>>()?; - Self::new(endpoints) + Ok(Self::new(endpoints)) }) - .ok() + .transpose() } pub fn publish(&self, event: BuilderEvent) {