Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion config.example.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
# The main configuration file for the Commit-Boost sidecar.
# Some fields are optional and can be omitted, in which case the default value, if present, will be used.

# Chain spec id. Supported values: Mainnet, Holesky, Helder
# Chain spec ID. Supported values:
# A network ID. Supported values: Mainnet, Holesky, Helder.
# A path to a chain spec file, either in .json format (e.g., as returned by the beacon endpoint /eth/v1/config/spec), or in .yml format (see examples in tests/data).
# A custom object, e.g., chain = { genesis_time_secs = 1695902400, slot_time_secs = 12, genesis_fork_version = "0x01017000" }.
chain = "Holesky"

# Configuration for the PBS module
Expand Down
36 changes: 32 additions & 4 deletions crates/cli/src/docker_init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ use std::{path::Path, vec};
use cb_common::{
config::{
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_URL_ENV,
CHAIN_SPEC_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_URL_ENV,
},
loader::SignerLoader,
types::ModuleId,
Expand Down Expand Up @@ -37,6 +37,7 @@ const SIGNER_NETWORK: &str = "signer_network";
pub fn handle_docker_init(config_path: String, output_dir: String) -> Result<()> {
println!("Initializing Commit-Boost with config file: {}", config_path);
let cb_config = CommitBoostConfig::from_file(&config_path)?;
let chain_spec_path = CommitBoostConfig::chain_spec_file(&config_path);

let metrics_enabled = cb_config.metrics.is_some();
let log_to_file = cb_config.logs.is_some();
Expand All @@ -46,6 +47,17 @@ pub fn handle_docker_init(config_path: String, output_dir: String) -> Result<()>

// config volume to pass to all services
let config_volume = Volumes::Simple(format!("./{}:{}:ro", config_path, CONFIG_DEFAULT));
let chain_spec_volume = chain_spec_path.as_ref().and_then(|p| {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe:

let get_file_name_str = |p: &Path| -> Option<&str> {
    p.file_name()?.to_str()
};

// chain_spec_volume using the helper
let chain_spec_volume = chain_spec_path.as_ref().and_then(|p| {
    let file_name = get_file_name_str(p)?;
    Some(Volumes::Simple(format!("{}:/{}:ro", p.display(), file_name)))
});

// chain_spec_env using the helper
let chain_spec_env = chain_spec_path.and_then(|p| {
    let file_name = get_file_name_str(&p)?;
    Some(get_env_val(CHAIN_SPEC_ENV, &format!("/{file_name}")))
});

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mm not sure this is more legible

// this is ok since the config has already been loaded once
let file_name = p.file_name()?.to_str()?;
Some(Volumes::Simple(format!("{}:/{}:ro", p.display(), file_name)))
});

let chain_spec_env = chain_spec_path.and_then(|p| {
// this is ok since the config has already been loaded once
let file_name = p.file_name()?.to_str()?;
Some(get_env_val(CHAIN_SPEC_ENV, &format!("/{file_name}")))
});

let mut jwts = IndexMap::new();
// envs to write in .env file
Expand Down Expand Up @@ -105,6 +117,9 @@ pub fn handle_docker_init(config_path: String, output_dir: String) -> Result<()>
// Set environment file
let env_file = module.env_file.map(EnvFile::Simple);

if let Some((key, val)) = chain_spec_env.clone() {
module_envs.insert(key, val);
}
if metrics_enabled {
let (key, val) = get_env_uval(METRICS_PORT_ENV, metrics_port as u64);
module_envs.insert(key, val);
Expand All @@ -125,6 +140,7 @@ pub fn handle_docker_init(config_path: String, output_dir: String) -> Result<()>

// volumes
let mut module_volumes = vec![config_volume.clone()];
module_volumes.extend(chain_spec_volume.clone());
module_volumes.extend(get_log_volume(&cb_config.logs, &module.id));

Service {
Expand All @@ -151,6 +167,9 @@ pub fn handle_docker_init(config_path: String, output_dir: String) -> Result<()>
get_env_uval(BUILDER_PORT_ENV, builder_events_port),
]);

if let Some((key, val)) = chain_spec_env.clone() {
module_envs.insert(key, val);
}
if metrics_enabled {
let (key, val) = get_env_uval(METRICS_PORT_ENV, metrics_port as u64);
module_envs.insert(key, val);
Expand All @@ -169,6 +188,7 @@ pub fn handle_docker_init(config_path: String, output_dir: String) -> Result<()>

// volumes
let mut module_volumes = vec![config_volume.clone()];
module_volumes.extend(chain_spec_volume.clone());
module_volumes.extend(get_log_volume(&cb_config.logs, &module.id));

Service {
Expand Down Expand Up @@ -197,6 +217,9 @@ pub fn handle_docker_init(config_path: String, output_dir: String) -> Result<()>

let mut pbs_envs = IndexMap::from([get_env_val(CONFIG_ENV, CONFIG_DEFAULT)]);

if let Some((key, val)) = chain_spec_env.clone() {
pbs_envs.insert(key, val);
}
if metrics_enabled {
let (key, val) = get_env_uval(METRICS_PORT_ENV, metrics_port as u64);
pbs_envs.insert(key, val);
Expand All @@ -213,6 +236,7 @@ pub fn handle_docker_init(config_path: String, output_dir: String) -> Result<()>

// volumes
let mut pbs_volumes = vec![config_volume.clone()];
pbs_volumes.extend(chain_spec_volume.clone());
pbs_volumes.extend(get_log_volume(&cb_config.logs, PBS_MODULE_NAME));

// networks
Expand Down Expand Up @@ -256,6 +280,9 @@ pub fn handle_docker_init(config_path: String, output_dir: String) -> Result<()>
get_env_uval(SIGNER_PORT_ENV, signer_port as u64),
]);

if let Some((key, val)) = chain_spec_env.clone() {
signer_envs.insert(key, val);
}
if metrics_enabled {
let (key, val) = get_env_uval(METRICS_PORT_ENV, metrics_port as u64);
signer_envs.insert(key, val);
Expand All @@ -270,6 +297,7 @@ pub fn handle_docker_init(config_path: String, output_dir: String) -> Result<()>

// volumes
let mut volumes = vec![config_volume.clone()];
volumes.extend(chain_spec_volume.clone());

// TODO: generalize this, different loaders may not need volumes but eg ports
match signer_config.loader {
Expand Down
1 change: 1 addition & 0 deletions crates/common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ tokio.workspace = true
toml.workspace = true
serde.workspace = true
serde_json.workspace = true
serde_yaml.workspace = true

# telemetry
tracing.workspace = true
Expand Down
3 changes: 3 additions & 0 deletions crates/common/src/config/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
pub const CONFIG_ENV: &str = "CB_CONFIG";
pub const CONFIG_DEFAULT: &str = "/cb-config.toml";

/// Path to the chain spec file
pub const CHAIN_SPEC_ENV: &str = "CB_CHAIN_SPEC";

/// Where to receive scrape requests from Prometheus
pub const METRICS_PORT_ENV: &str = "CB_METRICS_PORT";

Expand Down
54 changes: 49 additions & 5 deletions crates/common/src/config/mod.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
use std::path::PathBuf;

use eyre::Result;
use serde::{Deserialize, Serialize};

use crate::types::Chain;
use crate::types::{load_chain_from_file, Chain};

mod constants;
mod log;
mod metrics;
mod module;
mod pbs;
mod signer;
mod utils;

mod log;

pub use constants::*;
pub use log::*;
pub use metrics::*;
Expand All @@ -22,7 +23,6 @@ pub use utils::*;

#[derive(Debug, Deserialize, Serialize)]
pub struct CommitBoostConfig {
// TODO: generalize this with a spec file
pub chain: Chain,
pub relays: Vec<RelayConfig>,
pub pbs: StaticPbsConfig,
Expand All @@ -45,9 +45,53 @@ impl CommitBoostConfig {
Ok(config)
}

// When loading the config from the environment, it's important that every path
// is replaced with the correct value if the config is loaded inside a container
pub fn from_env_path() -> Result<Self> {
let config: Self = load_file_from_env(CONFIG_ENV)?;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wonder if we can do something like:

impl TryFrom<&'static str> for CommitBoostConfig

and then

let config = CommitBoostConfig::try_from(CONFIG_ENV)?;

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah think we can improve in general how configs are loaded, will keep it in a separate PR

let config = if let Ok(path) = std::env::var(CHAIN_SPEC_ENV) {
// if the chain spec file is set, load it separately
let chain: Chain = load_chain_from_file(path.parse()?)?;
let rest_config: HelperConfig = load_file_from_env(CONFIG_ENV)?;

CommitBoostConfig {
chain,
relays: rest_config.relays,
pbs: rest_config.pbs,
modules: rest_config.modules,
signer: rest_config.signer,
metrics: rest_config.metrics,
logs: rest_config.logs,
}
} else {
load_file_from_env(CONFIG_ENV)?
};

config.validate()?;
Ok(config)
}

/// Returns the path to the chain spec file if any
pub fn chain_spec_file(path: &str) -> Option<PathBuf> {
match load_from_file::<ChainConfig>(path) {
Ok(config) => Some(config.chain),
Err(_) => None,
}
}
}

/// Helper struct to load the chain spec file
#[derive(Deserialize)]
struct ChainConfig {
chain: PathBuf,
}

/// Helper struct to load the rest of the config
#[derive(Deserialize)]
struct HelperConfig {
relays: Vec<RelayConfig>,
pbs: StaticPbsConfig,
modules: Option<Vec<StaticModuleConfig>>,
signer: Option<SignerConfig>,
metrics: Option<MetricsConfig>,
logs: Option<LogsSettings>,
}
26 changes: 0 additions & 26 deletions crates/common/src/constants.rs
Original file line number Diff line number Diff line change
@@ -1,29 +1,3 @@
// TODO: replace with full chain spec, allow loading from file

pub const APPLICATION_BUILDER_DOMAIN: [u8; 4] = [0, 0, 0, 1];
pub const GENESIS_VALIDATORS_ROOT: [u8; 32] = [0; 32];
pub const COMMIT_BOOST_DOMAIN: [u8; 4] = [109, 109, 111, 67];

// MAINNET
pub const MAINNET_FORK_VERSION: [u8; 4] = [0u8; 4];
pub const MAINNET_BUILDER_DOMAIN: [u8; 32] = [
0, 0, 0, 1, 245, 165, 253, 66, 209, 106, 32, 48, 39, 152, 239, 110, 211, 9, 151, 155, 67, 0,
61, 35, 32, 217, 240, 232, 234, 152, 49, 169,
];
pub const MAINNET_GENESIS_TIME_SECONDS: u64 = 1606824023;

// HOLESKY
pub const HOLESKY_FORK_VERSION: [u8; 4] = [1, 1, 112, 0];
pub const HOLESKY_BUILDER_DOMAIN: [u8; 32] = [
0, 0, 0, 1, 91, 131, 162, 55, 89, 197, 96, 178, 208, 198, 69, 118, 225, 220, 252, 52, 234, 148,
196, 152, 143, 62, 13, 159, 119, 240, 83, 135,
];
pub const HOLESKY_GENESIS_TIME_SECONDS: u64 = 1695902400;

// HELDER
pub const HELDER_FORK_VERSION: [u8; 4] = [16, 0, 0, 0];
pub const HELDER_BUILDER_DOMAIN: [u8; 32] = [
0, 0, 0, 1, 148, 196, 26, 244, 132, 255, 247, 150, 73, 105, 224, 189, 217, 34, 248, 45, 255,
15, 75, 232, 122, 96, 208, 102, 76, 201, 209, 255,
];
pub const HELDER_GENESIS_TIME_SECONDS: u64 = 1718967660;
5 changes: 4 additions & 1 deletion crates/common/src/signature.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ pub fn compute_signing_root(object_root: [u8; 32], signing_domain: [u8; 32]) ->
signing_data.tree_hash_root().0
}

// NOTE: this currently works only for builder domain signatures and
// verifications
// ref: https://github.com/ralexstokes/ethereum-consensus/blob/cf3c404043230559660810bc0c9d6d5a8498d819/ethereum-consensus/src/builder/mod.rs#L26-L29
pub fn compute_domain(chain: Chain, domain_mask: [u8; 4]) -> [u8; 32] {
#[derive(Debug, TreeHash)]
struct ForkData {
Expand All @@ -35,7 +38,7 @@ pub fn compute_domain(chain: Chain, domain_mask: [u8; 4]) -> [u8; 32] {
let mut domain = [0u8; 32];
domain[..4].copy_from_slice(&domain_mask);

let fork_version = chain.fork_version();
let fork_version = chain.genesis_fork_version();
let fd = ForkData { fork_version, genesis_validators_root: GENESIS_VALIDATORS_ROOT };
let fork_data_root = fd.tree_hash_root();

Expand Down
Loading