Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bolt-boost module #207

Merged
merged 29 commits into from
Sep 5, 2024
Merged
Changes from 1 commit
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
9d259c6
wip
Sep 2, 2024
b226613
fix: add target/ to gitignore
Sep 2, 2024
51d808c
feat(bolt-boost): add bolt-boost initial implementation
Sep 2, 2024
1528cf9
feat(bolt-boost): add Dockerfile
Sep 2, 2024
4a7d822
refactor(sidecar): rm boost module
Sep 2, 2024
35b8479
refactor(bolt-boost): refactor modules
Sep 2, 2024
fe5a9cc
test(bolt-boost): start testing multiproofs
Sep 3, 2024
a6a4480
test(bolt-boost): start testing multiproofs
Sep 3, 2024
7974037
test(bolt-boost): succesful multiproof test
Sep 3, 2024
7fa6365
test(bolt-boost): add more tests & simple bench
Sep 3, 2024
3090292
wip
Sep 4, 2024
ceb7873
test(bolt-boost): testing
Sep 5, 2024
ba9a45b
test(bolt-boost): add fastssz multiproof verification test
Sep 5, 2024
2723539
misc: rm comments
Sep 5, 2024
aa9a529
feat(bolt-boost): clean up
Sep 5, 2024
1953bbe
doc(bolt-boost): comments
Sep 5, 2024
bb300b2
fix: merge conflict
Sep 5, 2024
c3ebd85
fix(bolt-boost): use main ssz_rs
Sep 5, 2024
fd75fd8
fix(bolt-boost): pin git deps
Sep 5, 2024
161c552
doc(bolt-boost): note on disabled test
Sep 5, 2024
0c90f5b
feat(bolt-boost): switch to `parking_lot::RwLock`
Sep 5, 2024
81f6d10
feat(bolt-boost): better conflict handling
Sep 5, 2024
d1edbb5
feat(bolt-boost): handle conflicting constraints
Sep 5, 2024
495c3c7
doc(bolt-boost): some comments on proofs
Sep 5, 2024
93594c8
fix(bolt-boost): address comments
Sep 5, 2024
68cf5c4
feat(bolt-boost): add metrics
Sep 5, 2024
e506ef6
misc(bolt-boost): rustfmt
Sep 5, 2024
eff7308
feat(bolt-boost): security improvements
Sep 5, 2024
85d795e
misc(bolt-boost): rustfmt
Sep 5, 2024
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
Prev Previous commit
Next Next commit
feat(bolt-boost): add bolt-boost initial implementation
  • Loading branch information
Jonas Bostoen committed Sep 2, 2024
commit 51d808c3834df8a72f33f44daf06c52736f2dc0c
4,961 changes: 4,961 additions & 0 deletions bolt-boost/Cargo.lock

Large diffs are not rendered by default.

40 changes: 40 additions & 0 deletions bolt-boost/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
[package]
name = "bolt-boost"
version = "0.1.0"
edition = "2021"

[dependencies]
# core
tokio = { version = "1", features = ["full"] }
axum = { version = "0.7", features = ["macros"] }
axum-extra = "0.9.3"
futures = "0.3"
async-trait = "0.1.82"
eyre = "0.6.12"
thiserror = "1.0.63"
reqwest = "0.12.7"

# crypto
ssz_rs = { git = "https://github.com/ralexstokes/ssz-rs" }

# tracing
tracing = "0.1.40"
tracing-subscriber = "0.3.18"

# serialization
serde = { version = "1.0.197", features = ["derive"] }
serde_json = "1.0.115"
ethereum_ssz = "0.5"
ethereum_ssz_derive = "0.5"

# alloy
alloy = { version = "0.2.0", features = [
"full",
"provider-trace-api",
"rpc-types-beacon",
"rpc-types-engine",
] }

# commit-boost
commit-boost = { git = "https://github.com/mempirate/commit-boost-client", branch = "feat/exports" }
cb-common = { git = "https://github.com/mempirate/commit-boost-client", branch = "feat/exports" }
3 changes: 3 additions & 0 deletions bolt-boost/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Bolt-Boost

Bolt-Boost is a [commit-boost](https://commit-boost.github.io/commit-boost-client) module that extends the default PBS module with the [constraints-API](https://chainbound.github.io/bolt-docs/api/builder).
114 changes: 114 additions & 0 deletions bolt-boost/src/constraints.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
use std::{
collections::HashMap,
sync::{Arc, RwLock},
};

use alloy::{consensus::TxEnvelope, eips::eip2718::Decodable2718, primitives::TxHash};
use cb_common::pbs::{DenebSpec, EthSpec, Transaction};
use commit_boost::prelude::tree_hash;
use tracing::trace;

use super::types::{ConstraintsMessage, HashTreeRoot};

#[derive(Debug)]
pub struct ConstraintsWithProofData {
pub message: ConstraintsMessage,
/// List of transaction hashes and corresponding hash tree roots. Same order
/// as the transactions in the `message`.
pub transactions: Vec<(TxHash, HashTreeRoot)>,
}

/// A concurrent cache of constraints.
#[derive(Clone, Default, Debug)]
pub struct ConstraintsCache {
cache: Arc<RwLock<HashMap<u64, Vec<ConstraintsWithProofData>>>>,
mempirate marked this conversation as resolved.
Show resolved Hide resolved
}

impl ConstraintsCache {
pub fn new() -> Self {
Self {
cache: Default::default(),
}
}

/// Checks if the constraints for the given slot conflict with the existing constraints.
/// Will check for:
/// - Multiple ToB constraints per slot
/// - Duplicates of the same transaction per slot
pub fn conflicts_with(&self, slot: &u64, constraints: &ConstraintsMessage) -> bool {
if let Some(saved_constraints) = self.cache.read().unwrap().get(slot) {
mempirate marked this conversation as resolved.
Show resolved Hide resolved
for saved_constraint in saved_constraints {
// Only 1 ToB constraint per slot
if constraints.top && saved_constraint.message.top {
return true;
}

// Check if the transactions are the same
for tx in &constraints.transactions {
if saved_constraint
.message
.transactions
.iter()
.any(|existing| tx == existing)
{
return true;
}
}
}
}

false
}

/// Inserts the constraints for the given slot. Also decodes the raw transactions to save their
/// transaction hashes and hash tree roots for later use. Will first check for conflicts, and return
/// false if there are any.
pub fn insert(&self, slot: u64, constraints: ConstraintsMessage) -> bool {
if self.conflicts_with(&slot, &constraints) {
return false;
}

let mut transactions = Vec::with_capacity(constraints.transactions.len());

for tx in &constraints.transactions {
let tx_hash = *TxEnvelope::decode_2718(&mut tx.as_ref())
.expect("Valid transaction encoding")
.tx_hash();

let tx_root = tree_hash::TreeHash::tree_hash_root(&Transaction::<
<DenebSpec as EthSpec>::MaxBytesPerTransaction,
>::from(tx.to_vec()));

trace!(?tx_hash, ?tx_root, "Decoded constraint tx");

transactions.push((tx_hash, tx_root));
}

// Wrap the constraints message with the transaction info
let message_with_txs = ConstraintsWithProofData {
message: constraints,
transactions,
};

if let Some(cs) = self.cache.write().unwrap().get_mut(&slot) {
cs.push(message_with_txs);
} else {
self.cache
.write()
.unwrap()
.insert(slot, vec![message_with_txs]);
}

true
}

/// Removes all constraints before the given slot.
pub fn remove_before(&self, slot: u64) {
self.cache.write().unwrap().retain(|k, _| *k >= slot);
}

/// Gets and removes the constraints for the given slot.
pub fn remove(&self, slot: u64) -> Option<Vec<ConstraintsWithProofData>> {
self.cache.write().unwrap().remove(&slot)
}
}
31 changes: 31 additions & 0 deletions bolt-boost/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
use axum::{http::StatusCode, response::IntoResponse};

#[derive(Debug)]
/// Errors that the PbsService returns to client
pub enum PbsClientError {
NoResponse,
NoPayload,
BadRequest,
}

impl PbsClientError {
pub fn status_code(&self) -> StatusCode {
match self {
PbsClientError::NoResponse => StatusCode::SERVICE_UNAVAILABLE,
PbsClientError::NoPayload => StatusCode::BAD_GATEWAY,
PbsClientError::BadRequest => StatusCode::BAD_REQUEST,
}
}
}

impl IntoResponse for PbsClientError {
fn into_response(self) -> axum::response::Response {
let msg = match self {
PbsClientError::NoResponse => "no response from relays",
PbsClientError::NoPayload => "no payload from relays",
PbsClientError::BadRequest => "bad request",
};

(self.status_code(), msg).into_response()
}
}
Loading
Loading