Skip to content

Commit

Permalink
feat: script to use remote docker context
Browse files Browse the repository at this point in the history
  • Loading branch information
merklefruit committed Jul 19, 2024
1 parent 48095c3 commit 221f6e2
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 52 deletions.
9 changes: 9 additions & 0 deletions Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,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

# show the logs for the bolt devnet for beacon node
beacon-dump:
@id=$(docker ps -n 100 | grep 'cl-1-lighthouse-geth' | awk -F' ' '{print $1}') && \
Expand Down Expand Up @@ -139,3 +144,7 @@ _push-images:
docker push ghcr.io/chainbound/bolt-relay:0.1.0
docker push ghcr.io/chainbound/bolt-sidecar:0.1.0
docker push ghcr.io/chainbound/bolt-mev-boost:0.1.0

# 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
43 changes: 23 additions & 20 deletions bolt-sidecar/src/builder/compat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,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
Expand All @@ -46,30 +45,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,
}
Expand Down
18 changes: 4 additions & 14 deletions bolt-sidecar/src/builder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,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.
Expand Down Expand Up @@ -125,27 +125,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)?;

// 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(())
Expand Down
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};
use alloy_primitives::{Address, Bytes, B256, U256};
use alloy_rpc_types::Block;
Expand Down Expand Up @@ -38,7 +40,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,
Expand Down Expand Up @@ -73,7 +74,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,
excess_blob_gas: u64,
Expand All @@ -86,8 +87,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>,
Expand Down Expand Up @@ -350,7 +350,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,
Expand Down Expand Up @@ -386,6 +386,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_eips::eip2718::Encodable2718;
Expand Down
29 changes: 16 additions & 13 deletions bolt-sidecar/src/primitives/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,27 +172,30 @@ 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(),
}
}
}

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),
}
}
}
Expand Down
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

# Check if the remotebeast context already exists on the system
context_exists=$(docker context ls --format '{{.Name}}' | grep -c '^remotebeast$')
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
else
echo "The remotebeast context already exists"
fi

0 comments on commit 221f6e2

Please sign in to comment.