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
66 changes: 66 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
name: CI fmt clippy and test

on:
pull_request:
branches: ["**"]

jobs:
rustfmt:
name: Format
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v2

- name: Install nightly toolchain with rustfmt available
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: nightly
override: true
components: rustfmt

- name: Run cargo fmt
uses: actions-rs/cargo@v1
continue-on-error: true # WARNING: only for this example, remove it!
with:
command: fmt
args: --all -- --check

clippy:
name: Lint
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v2

- name: Install stable toolchain with clippy available
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
components: clippy

- name: Run cargo clippy
uses: actions-rs/cargo@v1
with:
command: clippy
args: --all -- -D warnings
tests:
name: Test
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v2
- name: Install stable toolchain
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
- name: Run tests
uses: actions-rs/cargo@v1
with:
command: test
args: --all --verbose
67 changes: 67 additions & 0 deletions .github/workflows/docker-publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
name: Deploy Images to GHCR

on:
workflow_run:
workflows: [ "CI fmt clippy and test" ]
types:
- completed
push:
branches:
- main # Trigger only on push to main branch
tags: # Trigger on new tags
- 'v*'

jobs:
push-store-image:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: 'Checkout GitHub Action'
uses: actions/checkout@main

- name: 'Set up Docker Buildx'
uses: docker/setup-buildx-action@v1

- name: 'Login to GitHub Container Registry'
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: 'Extract short hash'
id: vars
run: echo "SHORT_SHA=$(git rev-parse --short HEAD)" >> $GITHUB_ENV # This sets the SHORT_SHA environment variable

- name: 'Set Docker tag'
id: docker_tag
run: |
if [[ "${{ github.ref }}" == refs/tags/* ]]; then
TAG_NAME=${{ github.ref }}
TAG_NAME=${TAG_NAME##*/}
echo "DOCKER_TAG=${TAG_NAME}" >> $GITHUB_ENV
else
echo "DOCKER_TAG=${{ env.SHORT_SHA }}" >> $GITHUB_ENV
fi

- name: Build and push pbs
uses: docker/build-push-action@v6
with:
context: .
push: true
tags: ghcr.io/commit-boost/commit-boost-client/pbs:${{ env.DOCKER_TAG }}
cache-from: type=gha
cache-to: type=gha,mode=max
file: docker/pbs.Dockerfile

- name: Build and push signer
uses: docker/build-push-action@v6
with:
context: .
push: true
tags: ghcr.io/commit-boost/commit-boost-client/signer:${{ env.DOCKER_TAG }}
cache-from: type=gha
cache-to: type=gha,mode=max
file: docker/signer.Dockerfile
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ Cargo.lock
*.env
*.docker-compose.yml
targets.json

.idea/
33 changes: 17 additions & 16 deletions crates/cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,9 @@ impl Args {

// Command::Start2 { config: config_path } => {
// let config = CommitBoostConfig::from_file(&config_path);
// let signer_config = config.signer.expect("missing signer config with modules");
// let metrics_config = config.metrics.clone().expect("missing metrics config");
// let signer_config = config.signer.expect("missing signer config with
// modules"); let metrics_config = config.metrics.clone().expect("missing
// metrics config");

// // TODO: Actually generate this token
// let pbs_jwt = "MY_PBS_TOKEN";
Expand All @@ -102,8 +103,8 @@ impl Args {
// let jwts: HashMap<String, String> =
// iter::once((DEFAULT_PBS_JWT_KEY.into(), pbs_jwt.into()))
// .chain(modules.iter().map(|module|
// // TODO: Generate token instead of hard-coding it. Think about persisting it
// across the project. (
// // TODO: Generate token instead of hard-coding it. Think
// about persisting it across the project. (
// module.id.clone(),
// MODULE_JWT.into()
// // format!("JWT_{}", module.id)
Expand All @@ -123,24 +124,24 @@ impl Args {
// image: Some(module.docker_image.clone()),
// host_config: Some(bollard::secret::HostConfig {
// binds: {
// let full_config_path = std::fs::canonicalize(&config_path)
// .unwrap()
// let full_config_path =
// std::fs::canonicalize(&config_path) .unwrap()
// .to_string_lossy()
// .to_string();
// Some(vec![format!("{}:{}", full_config_path, "/config.toml")])
// },
// network_mode: Some(String::from("host")), // Use the host network
// ..Default::default()
// Some(vec![format!("{}:{}", full_config_path,
// "/config.toml")]) },
// network_mode: Some(String::from("host")), // Use the host
// network ..Default::default()
// }),
// env: {
// let metrics_server_url = metrics_config.address;
// info!("Metrics");
// Some(vec![
// format!("{}={}", MODULE_ID_ENV, module.id),
// format!("{}={}", CB_CONFIG_ENV, "/config.toml"),
// format!("{}={}", MODULE_JWT_ENV, jwts.get(&module.id).unwrap()),
// format!("{}={}", METRICS_SERVER_ENV, metrics_server_url),
// ])
// format!("{}={}", MODULE_JWT_ENV,
// jwts.get(&module.id).unwrap()), format!("{}={}",
// METRICS_SERVER_ENV, metrics_server_url), ])
// },
// ..Default::default()
// };
Expand All @@ -160,9 +161,9 @@ impl Args {
// DockerMetricsCollector::new(
// vec![cid],
// metrics_config.address.clone(),
// // FIXME: The entire DockerMetricsCollector currently works with a
// // single JWT; need to migrate to per-module JWT.
// MODULE_JWT.to_string(),
// // FIXME: The entire DockerMetricsCollector currently
// works with a // single JWT; need to migrate to per-module
// JWT. MODULE_JWT.to_string(),
// )
// .await
// });
Expand Down
3 changes: 2 additions & 1 deletion crates/common/src/commit/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ use tree_hash_derive::TreeHash;

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

// TODO: might need to adapt the SignedProxyDelegation so that it goes through web3 signer
// TODO: might need to adapt the SignedProxyDelegation so that it goes through
// web3 signer
#[derive(Debug, Clone, Copy, Serialize, Deserialize, Encode, Decode, TreeHash)]
pub struct ProxyDelegation {
pub delegator: BlsPublicKey,
Expand Down
12 changes: 6 additions & 6 deletions crates/common/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,20 +44,20 @@ pub struct CommitBoostConfig {
}

fn load_from_file<T: DeserializeOwned>(path: &str) -> T {
let config_file =
std::fs::read_to_string(path).expect(&format!("Unable to find config file: '{}'", path));
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_file_from_env<T: DeserializeOwned>(env: &str) -> T {
let path = std::env::var(env).expect(&format!("{env} is not set"));
let path = std::env::var(env).unwrap_or_else(|_| panic!("{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).expect(&format!("{JWTS_ENV} is not set"));
serde_json::from_str(&jwts).expect(&format!("Failed to parse jwts: {jwts}"))
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}"))
}

impl CommitBoostConfig {
Expand Down Expand Up @@ -299,5 +299,5 @@ 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).expect(&format!("{env} is not set"))
std::env::var(env).unwrap_or_else(|_| panic!("{env} is not set"))
}
3 changes: 1 addition & 2 deletions crates/common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,4 @@ pub mod signer;
pub mod types;
pub mod utils;


pub const DEFAULT_REQUEST_TIMEOUT: Duration = Duration::from_secs(12);
pub const DEFAULT_REQUEST_TIMEOUT: Duration = Duration::from_secs(12);
8 changes: 4 additions & 4 deletions crates/common/src/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,16 @@ impl SignerLoader {
match self {
SignerLoader::File { .. } => {
let path = load_env_var_infallible(SIGNER_KEYS_ENV);
let file =
std::fs::read_to_string(path).expect(&format!("Unable to find keys file"));
let file = std::fs::read_to_string(path)
.unwrap_or_else(|_| panic!("Unable to find keys file"));

let keys: Vec<FileKey> = serde_json::from_str(&file).unwrap();

keys.into_iter().map(|k| Signer::new_from_bytes(&k.secret_key)).collect()
}
SignerLoader::ValidatorsDir { .. } => {
// TODO: hacky way to load for now, we should support reading the definitions.yml
// file
// TODO: hacky way to load for now, we should support reading the
// definitions.yml file
let keys_path = load_env_var_infallible(SIGNER_DIR_KEYS_ENV);
let secrets_path = load_env_var_infallible(SIGNER_DIR_SECRETS_ENV);
load_secrets_and_keys(keys_path, secrets_path).expect("failed to load signers")
Expand Down
30 changes: 17 additions & 13 deletions crates/pbs/src/mev_boost/get_header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,14 +121,16 @@ async fn send_timed_get_header(
loop {
handles.push(tokio::spawn(
send_one_get_header(
url.clone(),
params,
relay.clone(),
chain,
headers.clone(),
timeout_left_ms,
pbs_config.skip_sigverify,
pbs_config.min_bid_wei,
RequestConfig {
timeout_ms: timeout_left_ms,
url: url.clone(),
headers: headers.clone(),
},
)
.in_current_span(),
));
Expand Down Expand Up @@ -179,41 +181,43 @@ async fn send_timed_get_header(

// if no timing games or no repeated send, just send one request
send_one_get_header(
url,
params,
relay,
chain,
headers,
timeout_left_ms,
pbs_config.skip_sigverify,
pbs_config.min_bid_wei,
RequestConfig { timeout_ms: timeout_left_ms, url, headers },
)
.await
.map(|(_, maybe_header)| maybe_header)
}

async fn send_one_get_header(
struct RequestConfig {
url: String,
timeout_ms: u64,
headers: HeaderMap,
}

async fn send_one_get_header(
params: GetHeaderParams,
relay: RelayClient,
chain: Chain,
mut headers: HeaderMap,
timeout_ms: u64,
skip_sigverify: bool,
min_bid_wei: U256,
mut req_config: RequestConfig,
) -> Result<(u64, Option<GetHeaderReponse>), PbsError> {
// the timestamp in the header is the consensus block time which is fixed,
// use the beginning of the request as proxy to make sure we use only the
// last one received
let start_request_time = utcnow_ms();
headers.insert(HEADER_START_TIME_UNIX_MS, HeaderValue::from(start_request_time));
req_config.headers.insert(HEADER_START_TIME_UNIX_MS, HeaderValue::from(start_request_time));

let start_request = Instant::now();
let res = match relay
.client
.get(url)
.timeout(Duration::from_millis(timeout_ms))
.headers(headers)
.get(req_config.url)
.timeout(Duration::from_millis(req_config.timeout_ms))
.headers(req_config.headers)
.send()
.await
{
Expand Down
10 changes: 5 additions & 5 deletions crates/pbs/src/types/beacon_block.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use alloy::primitives::B256;
use alloy::rpc::types::beacon::BlsSignature;
use alloy::{primitives::B256, rpc::types::beacon::BlsSignature};
use serde::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode};

Expand Down Expand Up @@ -52,8 +51,8 @@ mod tests {
use super::{SignedBlindedBeaconBlock, SubmitBlindedBlockResponse};

#[test]
// this is from the builder api spec, but with sync_committee_bits fixed to deserialize
// correctly
// this is from the builder api spec, but with sync_committee_bits fixed to
// deserialize correctly
fn test_signed_blinded_block() {
let data = r#"{
"message": {
Expand Down Expand Up @@ -567,7 +566,8 @@ mod tests {
}

#[test]
// this is from the builder api spec, but with blobs fixed to deserialize correctly
// this is from the builder api spec, but with blobs fixed to deserialize
// correctly
fn test_submit_blinded_block_response() {
let blob = alloy::primitives::hex::encode([1; 131072]);
let data = format!(
Expand Down
8 changes: 4 additions & 4 deletions crates/pbs/src/types/blinded_block_body.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::usize;

use alloy::primitives::{Address, B256};
use alloy::rpc::types::beacon::{BlsPublicKey, BlsSignature};
use alloy::{
primitives::{Address, B256},
rpc::types::beacon::{BlsPublicKey, BlsSignature},
};
use cb_common::utils::as_str;
use serde::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode};
Expand Down
Loading