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
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ bollard = "0.16.1"
# misc
clap = { version = "4.5.4", features = ["derive", "env"] }
thiserror = "1.0.61"
color-eyre = "0.6.3"
eyre = "0.6.12"
url = "2.5.0"
uuid = { version = "1.8.0", features = ["v4", "fast-rng", "serde"] }
Expand Down
2 changes: 2 additions & 0 deletions bin/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ tracing-subscriber.workspace = true

# misc
clap.workspace = true
eyre.workspace = true
color-eyre.workspace = true

[[bin]]
name = "commit-boost"
Expand Down
4 changes: 3 additions & 1 deletion bin/commit_boost.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ use clap::Parser;

/// Main entry point of the Commit Boost CLI
#[tokio::main]
async fn main() {
async fn main() -> eyre::Result<()> {
color_eyre::install()?;
// set default backtrace unless provided
if std::env::var_os("RUST_BACKTRACE").is_none() {
std::env::set_var("RUST_BACKTRACE", "1");
Expand All @@ -14,4 +15,5 @@ async fn main() {
eprintln!("Error: {err}");
std::process::exit(1)
};
Ok(())
}
8 changes: 6 additions & 2 deletions bin/default_pbs.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
use cb_common::{config::load_pbs_config, utils::initialize_tracing_log};
use cb_pbs::{DefaultBuilderApi, PbsService, PbsState};
use eyre::Result;

#[tokio::main]
async fn main() {
async fn main() -> Result<()> {
color_eyre::install()?;

// set default backtrace unless provided
if std::env::var_os("RUST_BACKTRACE").is_none() {
std::env::set_var("RUST_BACKTRACE", "1");
Expand All @@ -14,6 +17,7 @@ async fn main() {
let pbs_config = load_pbs_config().expect("failed to load pbs config");
let state = PbsState::<()>::new(pbs_config);

PbsService::init_metrics();
PbsService::init_metrics()?;
PbsService::run::<(), DefaultBuilderApi>(state).await;
Ok(())
}
9 changes: 6 additions & 3 deletions bin/signer_module.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
use cb_common::{config::StartSignerConfig, utils::initialize_tracing_log};
use cb_signer::service::SigningService;
use eyre::Result;

#[tokio::main]
async fn main() {
async fn main() -> Result<()> {
color_eyre::install()?;

// set default backtrace unless provided
if std::env::var_os("RUST_BACKTRACE").is_none() {
std::env::set_var("RUST_BACKTRACE", "1");
}

initialize_tracing_log();

let config = StartSignerConfig::load_from_env();
SigningService::run(config).await;
let config = StartSignerConfig::load_from_env()?;
SigningService::run(config).await
}
8 changes: 5 additions & 3 deletions crates/cli/src/docker_cmd.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use std::process::{Command, Stdio};

pub fn handle_docker_start(compose_path: String, env_path: String) -> eyre::Result<()> {
use eyre::Result;

pub fn handle_docker_start(compose_path: String, env_path: String) -> Result<()> {
println!("Starting Commit-Boost with compose file: {}", compose_path);

// load env file
Expand All @@ -24,7 +26,7 @@ pub fn handle_docker_start(compose_path: String, env_path: String) -> eyre::Resu
Ok(())
}

pub fn handle_docker_stop(compose_path: String, env_path: String) -> eyre::Result<()> {
pub fn handle_docker_stop(compose_path: String, env_path: String) -> Result<()> {
println!("Stopping Commit-Boost with compose file: {}", compose_path);

// load env file
Expand All @@ -46,7 +48,7 @@ pub fn handle_docker_stop(compose_path: String, env_path: String) -> eyre::Resul
}

// TODO: we shouldnt use docker logs
pub fn handle_docker_logs(compose_path: String) -> eyre::Result<()> {
pub fn handle_docker_logs(compose_path: String) -> Result<()> {
println!("Querying Commit-Boost with compose file: {}", compose_path);

// TODO: if permission denied, print warning to run as sudo
Expand Down
7 changes: 4 additions & 3 deletions crates/cli/src/docker_init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use docker_compose_types::{
Compose, DependsOnOptions, Environment, LoggingParameters, MapOrEmpty, NetworkSettings,
Networks, Ports, Service, Services, SingleValue, Volumes,
};
use eyre::Result;
use indexmap::IndexMap;
use serde::Serialize;

Expand All @@ -28,10 +29,10 @@ const SIGNER_NETWORK: &str = "signer_network";

// TODO: do more validation for paths, images, etc
#[allow(unused_assignments)]
pub fn handle_docker_init(config_path: String, output_dir: String) -> eyre::Result<()> {
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 cb_config = CommitBoostConfig::from_file(&config_path)?;

let mut services = IndexMap::new();

Expand Down Expand Up @@ -158,7 +159,7 @@ pub fn handle_docker_init(config_path: String, output_dir: String) -> eyre::Resu
};

// write jwts to env
let jwts_json = serde_json::to_string(&jwts).unwrap().clone();
let jwts_json = serde_json::to_string(&jwts)?.clone();
envs.insert(JWTS_ENV.into(), format!("{jwts_json:?}"));

let signer_service = Service {
Expand Down
10 changes: 5 additions & 5 deletions crates/common/src/commit/client.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::sync::Arc;

use alloy::rpc::types::beacon::{BlsPublicKey, BlsSignature};
use eyre::WrapErr;
use reqwest::header::{HeaderMap, HeaderValue, AUTHORIZATION};
use serde::{Deserialize, Serialize};

Expand All @@ -27,21 +28,20 @@ pub struct SignerClient {

impl SignerClient {
/// Create a new SignerClient
pub fn new(signer_server_address: String, jwt: &str) -> Self {
pub fn new(signer_server_address: String, jwt: &str) -> eyre::Result<Self> {
let url = format!("http://{}", signer_server_address);
let mut headers = HeaderMap::new();

let mut auth_value =
HeaderValue::from_str(&format!("Bearer {}", jwt)).expect("invalid jwt");
HeaderValue::from_str(&format!("Bearer {}", jwt)).wrap_err("invalid jwt")?;
auth_value.set_sensitive(true);
headers.insert(AUTHORIZATION, auth_value);
let client = reqwest::Client::builder()
.timeout(DEFAULT_REQUEST_TIMEOUT)
.default_headers(headers)
.build()
.unwrap();
.build()?;

Self { url: url.into(), client }
Ok(Self { url: url.into(), client })
}

/// Request a list of validator pubkeys for which signatures can be
Expand Down
5 changes: 2 additions & 3 deletions crates/common/src/commit/request.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
use alloy::rpc::types::beacon::{BlsPublicKey, BlsSignature};
use blst::BLST_ERROR;
use serde::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode};
use tree_hash::TreeHash;
use tree_hash_derive::TreeHash;

use crate::{signature::verify_signed_builder_message, types::Chain};
use crate::{error::BlstErrorWrapper, signature::verify_signed_builder_message, types::Chain};

// TODO: might need to adapt the SignedProxyDelegation so that it goes through
// web3 signer
Expand All @@ -23,7 +22,7 @@ pub struct SignedProxyDelegation {
}

impl SignedProxyDelegation {
pub fn validate(&self, chain: Chain) -> Result<(), BLST_ERROR> {
pub fn validate(&self, chain: Chain) -> Result<(), BlstErrorWrapper> {
verify_signed_builder_message(
chain,
&self.message.delegator,
Expand Down
80 changes: 41 additions & 39 deletions crates/common/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{collections::HashMap, sync::Arc};

use eyre::{eyre, ContextCompat};
use eyre::{eyre, ContextCompat, Result, WrapErr};
use serde::{de::DeserializeOwned, Deserialize, Serialize};

use crate::{
Expand Down Expand Up @@ -43,29 +43,29 @@ pub struct CommitBoostConfig {
pub metrics: MetricsConfig,
}

fn load_from_file<T: DeserializeOwned>(path: &str) -> T {
let config_file = std::fs::read_to_string(path)
.unwrap_or_else(|_| panic!("Unable to find config file: '{}'", path));
toml::from_str(&config_file).unwrap()
fn load_from_file<T: DeserializeOwned>(path: &str) -> Result<T> {
let config_file =
std::fs::read_to_string(path).wrap_err(format!("Unable to find config file: {path}"))?;
toml::from_str(&config_file).wrap_err("could not deserialize toml from string")
}

fn load_file_from_env<T: DeserializeOwned>(env: &str) -> T {
let path = std::env::var(env).unwrap_or_else(|_| panic!("{env} is not set"));
fn load_file_from_env<T: DeserializeOwned>(env: &str) -> Result<T> {
let path = std::env::var(env).wrap_err(format!("{env} is not set"))?;
load_from_file(&path)
}

/// Loads a map of module id -> jwt token from a json env
fn load_jwts() -> HashMap<String, String> {
let jwts = std::env::var(JWTS_ENV).unwrap_or_else(|_| panic!("{JWTS_ENV} is not set"));
serde_json::from_str(&jwts).unwrap_or_else(|_| panic!("Failed to parse jwts: {jwts}"))
fn load_jwts() -> Result<HashMap<String, String>> {
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")
}

impl CommitBoostConfig {
pub fn from_file(path: &str) -> Self {
pub fn from_file(path: &str) -> Result<Self> {
load_from_file(path)
}

pub fn from_env_path() -> Self {
pub fn from_env_path() -> Result<Self> {
load_file_from_env(CB_CONFIG_ENV)
}
}
Expand All @@ -92,18 +92,18 @@ pub struct StartSignerConfig {
}

impl StartSignerConfig {
pub fn load_from_env() -> Self {
let config = CommitBoostConfig::from_env_path();
pub fn load_from_env() -> Result<Self> {
let config = CommitBoostConfig::from_env_path()?;

let jwts = load_jwts();
let server_port = load_env_var_infallible(SIGNER_SERVER_ENV).parse().unwrap();
let jwts = load_jwts()?;
let server_port = load_env_var(SIGNER_SERVER_ENV)?.parse()?;

StartSignerConfig {
Ok(StartSignerConfig {
chain: config.chain,
loader: config.signer.expect("Signer config is missing").loader,
server_port,
jwts,
}
})
}
}

Expand All @@ -121,9 +121,9 @@ pub struct ModuleMetricsConfig {
}

impl ModuleMetricsConfig {
pub fn load_from_env() -> Self {
let server_port = load_env_var_infallible(METRICS_SERVER_ENV).parse().unwrap();
ModuleMetricsConfig { server_port }
pub fn load_from_env() -> Result<Self> {
let server_port = load_env_var(METRICS_SERVER_ENV)?.parse()?;
Ok(ModuleMetricsConfig { server_port })
}
}

Expand Down Expand Up @@ -163,9 +163,10 @@ fn default_pbs() -> String {
}

/// Loads the default pbs config, i.e. with no signer client or custom data
pub fn load_pbs_config() -> eyre::Result<PbsModuleConfig<()>> {
let config = CommitBoostConfig::from_env_path();
let relay_clients = config.relays.into_iter().map(RelayClient::new).collect();
pub fn load_pbs_config() -> Result<PbsModuleConfig<()>> {
let config = CommitBoostConfig::from_env_path()?;
let relay_clients =
config.relays.into_iter().map(RelayClient::new).collect::<Result<Vec<RelayClient>>>()?;

Ok(PbsModuleConfig {
chain: config.chain,
Expand All @@ -177,7 +178,7 @@ pub fn load_pbs_config() -> eyre::Result<PbsModuleConfig<()>> {
}

/// Loads a custom pbs config, i.e. with signer client and/or custom data
pub fn load_pbs_custom_config<T: DeserializeOwned>() -> eyre::Result<PbsModuleConfig<T>> {
pub fn load_pbs_custom_config<T: DeserializeOwned>() -> Result<PbsModuleConfig<T>> {
#[derive(Debug, Deserialize)]
struct CustomPbsConfig<U> {
#[serde(flatten)]
Expand All @@ -194,17 +195,19 @@ pub fn load_pbs_custom_config<T: DeserializeOwned>() -> eyre::Result<PbsModuleCo
}

// load module config including the extra data (if any)
let cb_config: StubConfig<T> = load_file_from_env(CB_CONFIG_ENV);
let relay_clients = cb_config.relays.into_iter().map(RelayClient::new).collect();
let cb_config: StubConfig<T> = load_file_from_env(CB_CONFIG_ENV)?;
let relay_clients =
cb_config.relays.into_iter().map(RelayClient::new).collect::<Result<Vec<RelayClient>>>()?;

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_infallible(MODULE_JWT_ENV);
let signer_server_address = load_env_var_infallible(SIGNER_SERVER_ENV);
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))
} else {
None
};
}
.transpose()?;

Ok(PbsModuleConfig {
chain: cb_config.chain,
Expand Down Expand Up @@ -242,10 +245,10 @@ pub struct StartModuleConfig<T = ()> {
/// - [CB_CONFIG_ENV] - the path to the config file
/// - [MODULE_JWT_ENV] - the jwt token for the module
// TODO: add metrics url here
pub fn load_module_config<T: DeserializeOwned>() -> eyre::Result<StartModuleConfig<T>> {
let module_id = load_env_var_infallible(MODULE_ID_ENV);
let module_jwt = load_env_var_infallible(MODULE_JWT_ENV);
let signer_server_address = load_env_var_infallible(SIGNER_SERVER_ENV);
pub fn load_module_config<T: DeserializeOwned>() -> Result<StartModuleConfig<T>> {
let module_id = load_env_var(MODULE_ID_ENV)?;
let module_jwt = load_env_var(MODULE_JWT_ENV)?;
let signer_server_address = load_env_var(SIGNER_SERVER_ENV)?;

#[derive(Debug, Deserialize)]
struct ThisModuleConfig<U> {
Expand All @@ -269,7 +272,7 @@ pub fn load_module_config<T: DeserializeOwned>() -> eyre::Result<StartModuleConf
}

// load module config including the extra data (if any)
let cb_config: StubConfig<T> = load_file_from_env(CB_CONFIG_ENV);
let cb_config: StubConfig<T> = load_file_from_env(CB_CONFIG_ENV)?;

// find all matching modules config
let matches: Vec<ThisModuleConfig<T>> = cb_config
Expand All @@ -286,7 +289,7 @@ pub fn load_module_config<T: DeserializeOwned>() -> eyre::Result<StartModuleConf
.find(|m| m.static_config.id == module_id)
.wrap_err(format!("failed to find module for {module_id}"))?;

let signer_client = SignerClient::new(signer_server_address, &module_jwt);
let signer_client = SignerClient::new(signer_server_address, &module_jwt)?;

Ok(StartModuleConfig {
id: module_config.static_config.id,
Expand All @@ -297,7 +300,6 @@ pub fn load_module_config<T: DeserializeOwned>() -> eyre::Result<StartModuleConf
}
}

// TODO: propagate errors
pub fn load_env_var_infallible(env: &str) -> String {
std::env::var(env).unwrap_or_else(|_| panic!("{env} is not set"))
pub fn load_env_var(env: &str) -> Result<String> {
std::env::var(env).wrap_err("{env} is not set")
}
Loading