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

feat: small sidecar changes #151

Merged
merged 2 commits into from
Jul 25, 2024
Merged
Changes from 1 commit
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
9 changes: 9 additions & 0 deletions Justfile
merklefruit marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -56,6 +56,11 @@ sidecar-logs:
@id=$(docker ps -n 100 | grep sidecar | awk -F' ' '{print $1}') && \
docker logs -f $id

# show the logs for the bolt devnet beacon node
beacon-logs:
@id=$(docker ps -n 100 | grep 'cl-1-lighthouse-geth' | awk -F' ' '{print $1}') && \
docker logs -f $id
thedevbirb marked this conversation as resolved.
Show resolved Hide resolved

# show the logs for the bolt devnet for beacon node
beacon-logs:
@id=$(docker ps -n 100 | grep 'cl-1-lighthouse-geth' | awk -F' ' '{print $1}') && \
@@ -150,3 +155,7 @@ release tag:
cd mev-boost-relay && docker buildx build --platform linux/amd64,linux/arm64 -t ghcr.io/chainbound/bolt-relay:{{tag}} --push .
cd builder && docker buildx build --platform linux/amd64,linux/arm64 -t ghcr.io/chainbound/bolt-builder:{{tag}} --push .
cd mev-boost && docker buildx build --platform linux/amd64,linux/arm64 -t ghcr.io/chainbound/bolt-mev-boost:{{tag}} --push .

# setup the remote docker builder context from our private Tailnet server
setup-remote-builder:
chmod +x ./scripts/setup_remote_builder.sh && ./scripts/setup_remote_builder.sh
merklefruit marked this conversation as resolved.
Show resolved Hide resolved
43 changes: 23 additions & 20 deletions bolt-sidecar/src/builder/compat.rs
Original file line number Diff line number Diff line change
@@ -20,14 +20,13 @@ use ethereum_consensus::{
ssz::prelude::{ssz_rs, ByteList, ByteVector, HashTreeRoot, List},
types::mainnet::ExecutionPayload as ConsensusExecutionPayload,
};
use reth_primitives::{SealedBlock, SealedHeader, TransactionSigned, Withdrawals};
use reth_primitives::{SealedBlock, TransactionSigned, Withdrawals};

/// Compatibility: convert a sealed header into an ethereum-consensus execution payload header.
/// This requires recalculating the withdrals and transactions roots as SSZ instead of MPT roots.
pub(crate) fn to_execution_payload_header(
value: &SealedHeader,
sealed_block: &SealedBlock,
transactions: Vec<TransactionSigned>,
withdrawals: reth_primitives::Withdrawals,
) -> ConsensusExecutionPayloadHeader {
// Transactions and withdrawals are treated as opaque byte arrays in consensus types
let transactions_bytes = transactions
@@ -48,30 +47,34 @@ pub(crate) fn to_execution_payload_header(
let mut withdrawals_ssz: List<ConsensusWithdrawal, MAX_WITHDRAWALS_PER_PAYLOAD> =
List::default();

for w in withdrawals.iter() {
withdrawals_ssz.push(to_consensus_withdrawal(w));
if let Some(withdrawals) = sealed_block.withdrawals.as_ref() {
for w in withdrawals.iter() {
withdrawals_ssz.push(to_consensus_withdrawal(w));
}
}

let withdrawals_root = withdrawals_ssz
.hash_tree_root()
.expect("valid withdrawals root");

let header = &sealed_block.header;

ConsensusExecutionPayloadHeader {
parent_hash: to_bytes32(value.parent_hash),
fee_recipient: to_bytes20(value.beneficiary),
state_root: to_bytes32(value.state_root),
receipts_root: to_bytes32(value.receipts_root),
logs_bloom: to_byte_vector(value.logs_bloom),
prev_randao: to_bytes32(value.mix_hash),
block_number: value.number,
gas_limit: value.gas_limit,
gas_used: value.gas_used,
timestamp: value.timestamp,
extra_data: ByteList::try_from(value.extra_data.as_ref()).unwrap(),
base_fee_per_gas: ssz_rs::U256::from(value.base_fee_per_gas.unwrap_or_default()),
block_hash: to_bytes32(value.hash()),
blob_gas_used: value.blob_gas_used.unwrap_or_default(),
excess_blob_gas: value.excess_blob_gas.unwrap_or_default(),
parent_hash: to_bytes32(header.parent_hash),
fee_recipient: to_bytes20(header.beneficiary),
state_root: to_bytes32(header.state_root),
receipts_root: to_bytes32(header.receipts_root),
logs_bloom: to_byte_vector(header.logs_bloom),
prev_randao: to_bytes32(header.mix_hash),
block_number: header.number,
gas_limit: header.gas_limit,
gas_used: header.gas_used,
timestamp: header.timestamp,
extra_data: ByteList::try_from(header.extra_data.as_ref()).unwrap(),
base_fee_per_gas: ssz_rs::U256::from(header.base_fee_per_gas.unwrap_or_default()),
block_hash: to_bytes32(header.hash()),
blob_gas_used: header.blob_gas_used.unwrap_or_default(),
excess_blob_gas: header.excess_blob_gas.unwrap_or_default(),
transactions_root,
withdrawals_root,
}
18 changes: 4 additions & 14 deletions bolt-sidecar/src/builder/mod.rs
Original file line number Diff line number Diff line change
@@ -60,7 +60,7 @@ pub enum BuilderError {

/// Local builder instance that can ingest a sealed header and
/// create the corresponding builder bid ready for the Builder API.
#[allow(missing_debug_implementations)]
#[derive(Debug)]
pub struct LocalBuilder {
/// BLS credentials for the local builder. We use this to sign the
/// payload bid submissions built by the sidecar.
@@ -118,27 +118,17 @@ impl LocalBuilder {
};

// 2. create a signed builder bid with the sealed block header we just created
let eth_header = compat::to_execution_payload_header(
&sealed_block.header,
transactions,
sealed_block.withdrawals.unwrap_or_default(),
);
let eth_header = compat::to_execution_payload_header(&sealed_block, transactions);

// 3. sign the bid with the local builder's BLS key
let signed_bid = self.create_signed_builder_bid(value, eth_header, kzg_commitments)?;

// 4. prepare a get_payload response for when the beacon node will ask for it
let Some(get_payload_res) =
GetPayloadResponse::try_from_execution_payload(&payload_and_blobs)
else {
return Err(BuilderError::Custom(
"Failed to build get_payload response: invalid fork version".to_string(),
));
};
let get_payload_response = GetPayloadResponse::from(payload_and_blobs);

self.payload_and_bid = Some(PayloadAndBid {
bid: signed_bid,
payload: get_payload_res,
payload: get_payload_response,
});

Ok(())
21 changes: 16 additions & 5 deletions bolt-sidecar/src/builder/payload_builder.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::fmt;

use alloy::{
eips::{calc_excess_blob_gas, calc_next_block_base_fee, eip1559::BaseFeeParams},
primitives::{Address, Bytes, B256, U256},
@@ -39,7 +41,6 @@ const DEFAULT_EXTRA_DATA: [u8; 20] = [
///
/// Find more information about this process & its reasoning here:
/// <https://github.com/chainbound/bolt/discussions/59>
#[allow(missing_debug_implementations)]
pub struct FallbackPayloadBuilder {
extra_data: Bytes,
fee_recipient: Address,
@@ -74,7 +75,7 @@ impl FallbackPayloadBuilder {
/// beacon chain, while others are calculated locally or from the
/// transactions themselves.
#[derive(Debug, Default)]
pub struct Context {
struct Context {
extra_data: Bytes,
base_fee: u64,
blob_gas_used: u64,
@@ -88,8 +89,7 @@ pub struct Context {
}

#[derive(Debug, Default)]
#[allow(missing_docs)]
pub struct Hints {
struct Hints {
pub gas_used: Option<u64>,
pub receipts_root: Option<B256>,
pub logs_bloom: Option<Bloom>,
@@ -357,7 +357,7 @@ pub(crate) fn parse_geth_response(error: &str) -> Option<String> {
}

/// Build a header with the given hints and context values.
pub(crate) fn build_header_with_hints_and_context(
fn build_header_with_hints_and_context(
latest_block: &Block,
hints: &Hints,
context: &Context,
@@ -393,6 +393,17 @@ pub(crate) fn build_header_with_hints_and_context(
}
}

impl fmt::Debug for FallbackPayloadBuilder {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("FallbackPayloadBuilder")
.field("extra_data", &self.extra_data)
.field("fee_recipient", &self.fee_recipient)
.field("engine_hinter", &self.engine_hinter)
.field("slot_time_in_seconds", &self.slot_time_in_seconds)
.finish()
}
}

#[cfg(test)]
mod tests {
use alloy::{
30 changes: 17 additions & 13 deletions bolt-sidecar/src/primitives/mod.rs
Original file line number Diff line number Diff line change
@@ -170,27 +170,17 @@ pub enum GetPayloadResponse {
Capella(ExecutionPayload),
#[serde(rename = "deneb")]
Deneb(PayloadAndBlobs),
#[serde(rename = "electra")]
Electra(PayloadAndBlobs),
}

impl GetPayloadResponse {
pub fn try_from_execution_payload(exec_payload: &PayloadAndBlobs) -> Option<Self> {
match exec_payload.execution_payload.version() {
Fork::Capella => Some(GetPayloadResponse::Capella(
exec_payload.execution_payload.clone(),
)),
Fork::Bellatrix => Some(GetPayloadResponse::Bellatrix(
exec_payload.execution_payload.clone(),
)),
Fork::Deneb => Some(GetPayloadResponse::Deneb(exec_payload.clone())),
_ => None,
}
}

pub fn block_hash(&self) -> &Hash32 {
match self {
GetPayloadResponse::Capella(payload) => payload.block_hash(),
GetPayloadResponse::Bellatrix(payload) => payload.block_hash(),
GetPayloadResponse::Deneb(payload) => payload.execution_payload.block_hash(),
GetPayloadResponse::Electra(payload) => payload.execution_payload.block_hash(),
}
}

@@ -199,6 +189,20 @@ impl GetPayloadResponse {
GetPayloadResponse::Capella(payload) => payload,
GetPayloadResponse::Bellatrix(payload) => payload,
GetPayloadResponse::Deneb(payload) => &payload.execution_payload,
GetPayloadResponse::Electra(payload) => &payload.execution_payload,
}
}
}

impl From<PayloadAndBlobs> for GetPayloadResponse {
fn from(payload_and_blobs: PayloadAndBlobs) -> Self {
match payload_and_blobs.execution_payload.version() {
Fork::Phase0 => GetPayloadResponse::Capella(payload_and_blobs.execution_payload),
Fork::Altair => GetPayloadResponse::Capella(payload_and_blobs.execution_payload),
Fork::Capella => GetPayloadResponse::Capella(payload_and_blobs.execution_payload),
Fork::Bellatrix => GetPayloadResponse::Bellatrix(payload_and_blobs.execution_payload),
Fork::Deneb => GetPayloadResponse::Deneb(payload_and_blobs),
Fork::Electra => GetPayloadResponse::Electra(payload_and_blobs),
}
}
}
13 changes: 13 additions & 0 deletions scripts/setup_remote_builder.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/sh
merklefruit marked this conversation as resolved.
Show resolved Hide resolved

# Check if the remotebeast context already exists on the system
context_exists=$(docker context ls --format '{{.Name}}' | grep -c '^remotebeast$')
merklefruit marked this conversation as resolved.
Show resolved Hide resolved
if [ "$context_exists" -eq 0 ]; then
if docker context create remotebeast --docker "host=ssh://shared@remotebeast"; then
echo "Successfully created the remotebeast context"
else
echo "Failed to create the remotebeast context"
fi
merklefruit marked this conversation as resolved.
Show resolved Hide resolved
else
echo "The remotebeast context already exists"
fi