Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 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
618 changes: 541 additions & 77 deletions Cargo.lock

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[workspace]
members = ["benches/*", "bin", "crates/*", "examples/builder_log", "examples/da_commit", "examples/status_api", "tests"]
members = ["benches/*", "bin", "crates/*", "examples/da_commit", "examples/status_api", "tests"]
resolver = "2"

[workspace.package]
Expand All @@ -24,7 +24,6 @@ axum-extra = { version = "0.10.0", features = ["typed-header"] }
base64 = "0.22.1"
bimap = { version = "0.6.3", features = ["serde"] }
blsful = "2.5"
blst = "0.3.11"
bytes = "1.10.1"
cb-cli = { path = "crates/cli" }
cb-common = { path = "crates/common" }
Expand All @@ -38,7 +37,6 @@ ctr = "0.9.2"
derive_more = { version = "2.0.1", features = ["deref", "display", "from", "into"] }
docker-compose-types = "0.16.0"
docker-image = "0.2.1"
eth2_keystore = { git = "https://github.com/sigp/lighthouse", tag = "v7.0.1" }
ethereum_serde_utils = "0.7.0"
ethereum_ssz = "0.8"
ethereum_ssz_derive = "0.8"
Expand All @@ -48,6 +46,8 @@ headers = "0.4.0"
indexmap = "2.2.6"
jsonwebtoken = { version = "9.3.1", default-features = false }
lazy_static = "1.5.0"
lh_eth2_keystore = { package = "eth2_keystore", git = "https://github.com/sigp/lighthouse", tag = "v7.1.0" }
lh_types = { package = "types", git = "https://github.com/sigp/lighthouse", tag = "v7.1.0" }
parking_lot = "0.12.3"
pbkdf2 = "0.12.2"
prometheus = "0.13.4"
Expand Down
20 changes: 8 additions & 12 deletions benches/pbs/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
use std::time::{Duration, Instant};

use alloy::{primitives::B256, rpc::types::beacon::BlsPublicKey};
use alloy::primitives::B256;
use cb_common::{
config::RelayConfig,
pbs::{GetHeaderResponse, RelayClient, RelayEntry},
signer::BlsSecretKey,
pbs::{BlsPublicKey, BlsSecretKey, GetHeaderResponse, RelayClient, RelayEntry},
types::Chain,
utils::blst_pubkey_to_alloy,
utils::TestRandomSeed,
};
use cb_tests::mock_relay::{start_mock_relay_service, MockRelayState};
use comfy_table::Table;
Expand All @@ -18,9 +17,6 @@ mod config;
fn get_random_hash() -> B256 {
B256::from(rand::random::<[u8; 32]>())
}
fn get_random_pubkey() -> BlsPublicKey {
BlsPublicKey::ZERO
}

#[tokio::main]
async fn main() {
Expand All @@ -46,8 +42,8 @@ async fn main() {
// bench
for slot in 0..config.benchmark.n_slots {
let parent_hash = get_random_hash();
let validator_pubkey = get_random_pubkey();
let url = mock_validator.get_header_url(slot, parent_hash, validator_pubkey).unwrap();
let validator_pubkey = BlsPublicKey::test_random();
let url = mock_validator.get_header_url(slot, &parent_hash, &validator_pubkey).unwrap();

for _ in 0..config.benchmark.headers_per_slot {
let url = url.clone();
Expand Down Expand Up @@ -138,8 +134,8 @@ const MOCK_RELAY_SECRET: [u8; 32] = [
152, 98, 59, 240, 181, 131, 47, 1, 180, 255, 245,
];
async fn start_mock_relay(chain: Chain, relay_config: RelayConfig) {
let signer = BlsSecretKey::key_gen(&MOCK_RELAY_SECRET, &[]).unwrap();
let pubkey: BlsPublicKey = blst_pubkey_to_alloy(&signer.sk_to_pk());
let signer = BlsSecretKey::deserialize(&MOCK_RELAY_SECRET).unwrap();
let pubkey: BlsPublicKey = signer.public_key();

assert_eq!(relay_config.entry.pubkey, pubkey, "Expected relay pubkey to be 0xb060572f535ba5615b874ebfef757fbe6825352ad257e31d724e57fe25a067a13cfddd0f00cb17bf3a3d2e901a380c17");

Expand All @@ -152,7 +148,7 @@ async fn start_mock_relay(chain: Chain, relay_config: RelayConfig) {
}

fn get_mock_validator(bench: BenchConfig) -> RelayClient {
let entry = RelayEntry { id: bench.id, pubkey: BlsPublicKey::default(), url: bench.url };
let entry = RelayEntry { id: bench.id, pubkey: BlsPublicKey::test_random(), url: bench.url };
let config = RelayConfig {
entry,
id: None,
Expand Down
4 changes: 2 additions & 2 deletions bin/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ pub mod prelude {
load_builder_module_config, load_commit_module_config, load_pbs_config,
load_pbs_custom_config, LogsSettings, StartCommitModuleConfig, PBS_MODULE_NAME,
},
pbs::{BuilderEvent, BuilderEventClient, OnBuilderApiEvent},
signer::{BlsPublicKey, BlsSignature, EcdsaSignature},
pbs::{BlsPublicKey, BlsSignature},
signer::EcdsaSignature,
types::Chain,
utils::{initialize_tracing_log, utcnow_ms, utcnow_ns, utcnow_sec, utcnow_us},
};
Expand Down
5 changes: 2 additions & 3 deletions config.example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -239,15 +239,14 @@ proxy_dir = "./proxies"
# secrets_path = "./tests/data/proxy/secrets"

# Commit-Boost can optionally run "modules" which extend the capabilities of the sidecar.
# Currently, two types of modules are supported:
# Currently, one type of module is currently supported:
# - "commit": modules which request commitment signatures from the validator keys
# - "events": modules which callback to BuilderAPI events as triggered from the PBS modules, used e.g. for monitoring
# If any "commit" module is present, then the [signer] section should also be configured
# OPTIONAL
[[modules]]
# Unique ID of the module
id = "DA_COMMIT"
# Type of the module. Supported values: commit, events
# Type of the module. Supported values: commit
type = "commit"
# Docker image of the module
docker_image = "test_da_commit"
Expand Down
79 changes: 9 additions & 70 deletions crates/cli/src/docker_init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,15 @@ use std::{

use cb_common::{
config::{
CommitBoostConfig, LogsSettings, ModuleKind, SignerConfig, SignerType, BUILDER_PORT_ENV,
BUILDER_URLS_ENV, CHAIN_SPEC_ENV, CONFIG_DEFAULT, CONFIG_ENV, DIRK_CA_CERT_DEFAULT,
DIRK_CA_CERT_ENV, DIRK_CERT_DEFAULT, DIRK_CERT_ENV, DIRK_DIR_SECRETS_DEFAULT,
DIRK_DIR_SECRETS_ENV, DIRK_KEY_DEFAULT, DIRK_KEY_ENV, JWTS_ENV, LOGS_DIR_DEFAULT,
LOGS_DIR_ENV, METRICS_PORT_ENV, MODULE_ID_ENV, MODULE_JWT_ENV, PBS_ENDPOINT_ENV,
PBS_MODULE_NAME, PROXY_DIR_DEFAULT, PROXY_DIR_ENV, PROXY_DIR_KEYS_DEFAULT,
PROXY_DIR_KEYS_ENV, PROXY_DIR_SECRETS_DEFAULT, PROXY_DIR_SECRETS_ENV, SIGNER_DEFAULT,
SIGNER_DIR_KEYS_DEFAULT, SIGNER_DIR_KEYS_ENV, SIGNER_DIR_SECRETS_DEFAULT,
SIGNER_DIR_SECRETS_ENV, SIGNER_ENDPOINT_ENV, SIGNER_KEYS_ENV, SIGNER_MODULE_NAME,
SIGNER_URL_ENV,
CommitBoostConfig, LogsSettings, ModuleKind, SignerConfig, SignerType, CHAIN_SPEC_ENV,
CONFIG_DEFAULT, CONFIG_ENV, DIRK_CA_CERT_DEFAULT, DIRK_CA_CERT_ENV, DIRK_CERT_DEFAULT,
DIRK_CERT_ENV, DIRK_DIR_SECRETS_DEFAULT, DIRK_DIR_SECRETS_ENV, DIRK_KEY_DEFAULT,
DIRK_KEY_ENV, JWTS_ENV, LOGS_DIR_DEFAULT, LOGS_DIR_ENV, METRICS_PORT_ENV, MODULE_ID_ENV,
MODULE_JWT_ENV, PBS_ENDPOINT_ENV, PBS_MODULE_NAME, PROXY_DIR_DEFAULT, PROXY_DIR_ENV,
PROXY_DIR_KEYS_DEFAULT, PROXY_DIR_KEYS_ENV, PROXY_DIR_SECRETS_DEFAULT,
PROXY_DIR_SECRETS_ENV, SIGNER_DEFAULT, SIGNER_DIR_KEYS_DEFAULT, SIGNER_DIR_KEYS_ENV,
SIGNER_DIR_SECRETS_DEFAULT, SIGNER_DIR_SECRETS_ENV, SIGNER_ENDPOINT_ENV, SIGNER_KEYS_ENV,
SIGNER_MODULE_NAME, SIGNER_URL_ENV,
},
pbs::{BUILDER_API_PATH, GET_STATUS_PATH},
signer::{ProxyStore, SignerLoader, DEFAULT_SIGNER_PORT},
Expand Down Expand Up @@ -81,9 +80,6 @@ pub async fn handle_docker_init(config_path: PathBuf, output_dir: PathBuf) -> Re
format!("http://cb_signer:{signer_port}")
};

let builder_events_port = 30000;
let mut builder_events_modules = Vec::new();

let mut warnings = Vec::new();

let needs_signer_module = cb_config.pbs.with_signer ||
Expand Down Expand Up @@ -185,58 +181,6 @@ pub async fn handle_docker_init(config_path: PathBuf, output_dir: PathBuf) -> Re
..Service::default()
}
}
// an event module just needs a port to listen on
ModuleKind::Events => {
let mut ports = vec![];
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(CONFIG_ENV, CONFIG_DEFAULT),
get_env_uval(BUILDER_PORT_ENV, builder_events_port),
]);

if let Some((key, val)) = chain_spec_env.clone() {
module_envs.insert(key, val);
}
if let Some(metrics_config) = &cb_config.metrics {
if metrics_config.enabled {
let host_endpoint =
SocketAddr::from((metrics_config.host, metrics_port));
ports.push(format!("{}:{}", host_endpoint, metrics_port));
warnings.push(format!(
"{} has an exported port on {}",
module_cid, metrics_port
));
targets.push(format!("{host_endpoint}"));
let (key, val) = get_env_uval(METRICS_PORT_ENV, metrics_port as u64);
module_envs.insert(key, val);

metrics_port += 1;
}
}
if log_to_file {
let (key, val) = get_env_val(LOGS_DIR_ENV, LOGS_DIR_DEFAULT);
module_envs.insert(key, val);
}

// 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 {
container_name: Some(module_cid.clone()),
image: Some(module.docker_image),
ports: Ports::Short(ports),
volumes: module_volumes,
environment: Environment::KvPair(module_envs),
depends_on: DependsOnOptions::Simple(vec!["cb_pbs".to_owned()]),
..Service::default()
}
}
};

services.insert(module_cid, Some(module_service));
Expand Down Expand Up @@ -283,11 +227,6 @@ pub async fn handle_docker_init(config_path: PathBuf, output_dir: PathBuf) -> Re
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_URLS_ENV, &env);
pbs_envs.insert(k, v);
}

// inside the container expose on 0.0.0.0
let container_endpoint =
Expand Down
4 changes: 2 additions & 2 deletions crates/common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,19 @@ async-trait.workspace = true
axum.workspace = true
base64.workspace = true
bimap.workspace = true
blst.workspace = true
bytes.workspace = true
cipher.workspace = true
ctr.workspace = true
derive_more.workspace = true
docker-image.workspace = true
eth2_keystore.workspace = true
ethereum_serde_utils.workspace = true
ethereum_ssz.workspace = true
ethereum_ssz_derive.workspace = true
eyre.workspace = true
futures.workspace = true
jsonwebtoken.workspace = true
lh_eth2_keystore.workspace = true
lh_types.workspace = true
pbkdf2.workspace = true
rand.workspace = true
rayon.workspace = true
Expand Down
5 changes: 3 additions & 2 deletions crates/common/src/commit/client.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::time::{Duration, Instant};

use alloy::{primitives::Address, rpc::types::beacon::BlsSignature};
use alloy::primitives::Address;
use eyre::WrapErr;
use reqwest::header::{HeaderMap, HeaderValue, AUTHORIZATION};
use serde::Deserialize;
Expand All @@ -16,7 +16,8 @@ use super::{
};
use crate::{
constants::SIGNER_JWT_EXPIRATION,
signer::{BlsPublicKey, EcdsaSignature},
pbs::{BlsPublicKey, BlsSignature},
signer::EcdsaSignature,
types::{Jwt, ModuleId},
utils::create_jwt,
DEFAULT_REQUEST_TIMEOUT,
Expand Down
35 changes: 23 additions & 12 deletions crates/common/src/commit/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,37 @@ use std::{
use alloy::{
hex,
primitives::{Address, B256},
rpc::types::beacon::BlsSignature,
};
use derive_more::derive::From;
use serde::{Deserialize, Serialize};
use tree_hash::TreeHash;
use tree_hash_derive::TreeHash;

use crate::{
constants::COMMIT_BOOST_DOMAIN, error::BlstErrorWrapper, signature::verify_signed_message,
signer::BlsPublicKey, types::Chain,
constants::COMMIT_BOOST_DOMAIN,
pbs::{BlsPublicKey, BlsSignature},
signature::verify_signed_message,
types::Chain,
};

pub trait ProxyId: AsRef<[u8]> + Debug + Clone + Copy + TreeHash + Display {}
pub trait ProxyId: Debug + Clone + TreeHash + Display {
fn to_bytes(&self) -> Vec<u8>;
}

impl ProxyId for Address {}
impl ProxyId for Address {
fn to_bytes(&self) -> Vec<u8> {
self.0.as_slice().to_vec()
}
}

impl ProxyId for BlsPublicKey {}
impl ProxyId for BlsPublicKey {
fn to_bytes(&self) -> Vec<u8> {
self.serialize().to_vec()
}
}

// GENERIC PROXY DELEGATION
#[derive(Debug, Clone, Copy, Serialize, Deserialize, TreeHash)]
#[derive(Debug, Clone, Serialize, Deserialize, TreeHash)]
pub struct ProxyDelegation<T: ProxyId> {
pub delegator: BlsPublicKey,
pub proxy: T,
Expand All @@ -40,7 +51,7 @@ impl<T: ProxyId> fmt::Display for ProxyDelegation<T> {
}
}

#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SignedProxyDelegation<T: ProxyId> {
pub message: ProxyDelegation<T>,
/// Signature of message with the delegator keypair
Expand All @@ -51,7 +62,7 @@ pub type SignedProxyDelegationBls = SignedProxyDelegation<BlsPublicKey>;
pub type SignedProxyDelegationEcdsa = SignedProxyDelegation<Address>;

impl<T: ProxyId> SignedProxyDelegation<T> {
pub fn validate(&self, chain: Chain) -> Result<(), BlstErrorWrapper> {
pub fn validate(&self, chain: Chain) -> bool {
verify_signed_message(
chain,
&self.message.delegator,
Expand Down Expand Up @@ -250,7 +261,7 @@ mod tests {

#[test]
fn test_decode_response_signature() {
let data = r#""0xa3ffa9241f78279f1af04644cb8c79c2d8f02bcf0e28e2f186f6dcccac0a869c2be441fda50f0dea895cfce2e53f0989a3ffa9241f78279f1af04644cb8c79c2d8f02bcf0e28e2f186f6dcccac0a869c2be441fda50f0dea895cfce2e53f0989""#;
let data = r#""0xc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000""#;
let _: BlsSignature = serde_json::from_str(data).unwrap();

let data = r#""0x985b495f49d1b96db3bba3f6c5dd1810950317c10d4c2042bd316f338cdbe74359072e209b85e56ac492092d7860063dd096ca31b4e164ef27e3f8d508e656801c""#;
Expand Down Expand Up @@ -283,7 +294,7 @@ mod tests {
"delegator": "0xa3366b54f28e4bf1461926a3c70cdb0ec432b5c92554ecaae3742d33fb33873990cbed1761c68020e6d3c14d30a22050",
"proxy": "0xa3366b54f28e4bf1461926a3c70cdb0ec432b5c92554ecaae3742d33fb33873990cbed1761c68020e6d3c14d30a22050"
},
"signature": "0xa3ffa9241f78279f1af04644cb8c79c2d8f02bcf0e28e2f186f6dcccac0a869c2be441fda50f0dea895cfce2e53f0989a3ffa9241f78279f1af04644cb8c79c2d8f02bcf0e28e2f186f6dcccac0a869c2be441fda50f0dea895cfce2e53f0989"
"signature": "0xc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
}"#;

let _: SignedProxyDelegationBls = serde_json::from_str(data).unwrap();
Expand All @@ -293,7 +304,7 @@ mod tests {
"delegator": "0xa3366b54f28e4bf1461926a3c70cdb0ec432b5c92554ecaae3742d33fb33873990cbed1761c68020e6d3c14d30a22050",
"proxy": "0x4ca9939a8311a7cab3dde201b70157285fa81a9d"
},
"signature": "0xa3ffa9241f78279f1af04644cb8c79c2d8f02bcf0e28e2f186f6dcccac0a869c2be441fda50f0dea895cfce2e53f0989a3ffa9241f78279f1af04644cb8c79c2d8f02bcf0e28e2f186f6dcccac0a869c2be441fda50f0dea895cfce2e53f0989"
"signature": "0xc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
}"#;

let _: SignedProxyDelegationEcdsa = serde_json::from_str(data).unwrap();
Expand Down
7 changes: 0 additions & 7 deletions crates/common/src/config/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,6 @@ 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";

/// Where to receive BuilderAPI calls from beacon node
pub const PBS_ENDPOINT_ENV: &str = "CB_PBS_ENDPOINT";

Expand Down Expand Up @@ -90,7 +87,3 @@ pub const MODULE_ID_ENV: &str = "CB_MODULE_ID";
pub const MODULE_JWT_ENV: &str = "CB_SIGNER_JWT";
/// Where to send signature request
pub const SIGNER_URL_ENV: &str = "CB_SIGNER_URL";

/// Events modules
/// Where to receive builder events
pub const BUILDER_PORT_ENV: &str = "CB_BUILDER_PORT";
Loading
Loading