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(mev-build-rs): Build Identifier Caching #202

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
feat(mev-build-rs): Build Identifier Caching
  • Loading branch information
refcell committed Nov 11, 2023
commit 993c3d895134ba8e2f4d27e77ad7fbc9fcb26cca
2 changes: 1 addition & 1 deletion mev-build-rs/src/reth_builder/bidder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ impl Bidder for DeadlineBidder {
let slot = build.context.slot;
let target = self.clock.duration_until_slot(slot);
let duration = target.checked_sub(self.deadline).unwrap_or_default();
let id = build.context.id();
let id = build.context.id().map_err(|_| Error::Internal("missing build id"))?;
tracing::debug!(%id, slot, ?duration, "waiting to submit bid");
tokio::time::sleep(duration).await;

Expand Down
58 changes: 44 additions & 14 deletions mev-build-rs/src/reth_builder/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ use mev_rs::{
};
use reth_primitives::{Bytes, ChainSpec, SealedBlock, Withdrawal, B256, U256};
use revm::primitives::{BlockEnv, CfgEnv};
use std::sync::{Arc, Mutex};
use std::{
collections::HashMap,
sync::{Arc, Mutex},
};

pub type BuildIdentifier = ByteVector<4>;

Expand Down Expand Up @@ -67,21 +70,46 @@ pub struct BuildContext {
pub bid_percent: f64,
// Amount to add to the block's value to bid to the proposer
pub subsidy: U256,
/// An internal cache of computed build context ids
pub id_cache: Arc<Mutex<HashMap<Vec<u8>, BuildIdentifier>>>,
}

pub fn compute_build_id(
slot: &Slot,
parent_hash: &B256,
proposer: &BlsPublicKey,
) -> Result<BuildIdentifier, Error> {
let id = compute_serialized_id(slot, parent_hash, proposer)?;
hash_serialized_id(id)
}

pub fn compute_build_id(slot: Slot, parent_hash: B256, proposer: &BlsPublicKey) -> BuildIdentifier {
pub fn compute_serialized_id(
slot: &Slot,
parent_hash: &B256,
proposer: &BlsPublicKey,
) -> Result<Vec<u8>, Error> {
let mut data = Vec::with_capacity(88);
slot.serialize(&mut data).expect("can serialize");
parent_hash.serialize(&mut data).expect("can serialize");
proposer.serialize(&mut data).expect("can serialize");
let summary = hash(data);
summary.as_ref()[..4].try_into().unwrap()
slot.serialize(&mut data).map_err(|_| Error::Internal("slot serialization failed"))?;
parent_hash
.serialize(&mut data)
.map_err(|_| Error::Internal("parent hash serialization failed"))?;
proposer.serialize(&mut data).map_err(|_| Error::Internal("proposer serialization failed"))?;
Ok(data)
}

pub fn hash_serialized_id(id: Vec<u8>) -> Result<BuildIdentifier, Error> {
let summary = hash(id);
summary.as_ref()[..4].try_into().map_err(|_| Error::Internal("build id hashing failed"))
}

impl BuildContext {
pub fn id(&self) -> BuildIdentifier {
// TODO: cache this
compute_build_id(self.slot, self.parent_hash, &self.proposer)
pub fn id(&self) -> Result<BuildIdentifier, Error> {
let serialized_id = compute_serialized_id(&self.slot, &self.parent_hash, &self.proposer)?;
let cache = self.id_cache.lock().map_err(|_| Error::Internal("id_cache lock poisoned"))?;
if let Some(id) = cache.get(&serialized_id) {
return Ok(id.clone())
}
hash_serialized_id(serialized_id)
}

pub fn base_fee(&self) -> u64 {
Expand Down Expand Up @@ -127,10 +155,12 @@ impl Build {
let build_context = &self.context;
let state = self.state.lock().unwrap();
let payload_with_payments = &state.payload_with_payments;
let payload = payload_with_payments
.payload
.as_ref()
.ok_or_else(|| Error::PayloadNotPrepared(build_context.id()))?;
let payload = payload_with_payments.payload.as_ref().ok_or_else(|| {
build_context
.id()
.map(Error::PayloadNotPrepared)
.unwrap_or(Error::Internal("Failed to compute build id"))
})?;
let payment = &payload_with_payments.proposer_payment;
let builder_payment = payload_with_payments.builder_payment;
Ok((
Expand Down
4 changes: 3 additions & 1 deletion mev-build-rs/src/reth_builder/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,7 @@ impl<Pool: TransactionPool, Client: StateProviderFactory + BlockReaderIdExt> Bui
gas_reserve: 21000,
bid_percent: self.bid_percent,
subsidy: subsidy_in_wei,
id_cache: Default::default(),
};
Ok(context)
}
Expand All @@ -313,7 +314,8 @@ impl<Pool: TransactionPool, Client: StateProviderFactory + BlockReaderIdExt> Bui
let mut state = self.state.lock().expect("can lock");
let mut new_builds = vec![];
for (proposer, relays) in proposals {
let build_identifier = compute_build_id(slot, parent_hash, &proposer.public_key);
let build_identifier = compute_build_id(&slot, &parent_hash, &proposer.public_key)
.map_err(|_| Error::Internal("failed to compute build id"))?;

if state.builds.contains_key(&build_identifier) {
return Ok(PayloadAttributesProcessingOutcome::Duplicate(payload_attributes))
Expand Down