Skip to content

Commit

Permalink
wip: refactor to use polymorphic types
Browse files Browse the repository at this point in the history
  • Loading branch information
ralexstokes committed Oct 13, 2023
1 parent 929e391 commit f848936
Show file tree
Hide file tree
Showing 18 changed files with 222 additions and 596 deletions.
21 changes: 13 additions & 8 deletions mev-boost-rs/src/relay_mux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ const PROPOSAL_TOLERANCE_DELAY: Slot = 1;
const FETCH_BEST_BID_TIME_OUT_SECS: u64 = 1;

fn bid_key_from(signed_block: &SignedBlindedBeaconBlock, public_key: &BlsPublicKey) -> BidRequest {
let slot = signed_block.slot();
let parent_hash = signed_block.parent_hash().clone();
let slot = *signed_block.message().slot();
let parent_hash =
signed_block.message().body().execution_payload_header().parent_hash().clone();

BidRequest { slot, parent_hash, public_key: public_key.clone() }
}
Expand All @@ -35,9 +36,10 @@ fn validate_bid(
public_key: &BlsPublicKey,
context: &Context,
) -> Result<(), Error> {
if bid.public_key() != public_key {
let bid_public_key = &bid.message.public_key;
if bid_public_key != public_key {
return Err(Error::BidPublicKeyMismatch {
bid: bid.public_key().clone(),
bid: bid_public_key.clone(),
relay: public_key.clone(),
})
}
Expand Down Expand Up @@ -169,7 +171,7 @@ impl BlindedBlockProvider for RelayMux {

// TODO: change `value` so it does the copy internally
let mut best_bid_indices =
select_best_bids(bids.iter().map(|(_, bid)| bid.value().clone()).enumerate());
select_best_bids(bids.iter().map(|(_, bid)| bid.message.value.clone()).enumerate());

// if multiple distinct bids with same bid value, break tie by randomly picking one
let mut rng = rand::thread_rng();
Expand All @@ -179,12 +181,12 @@ impl BlindedBlockProvider for RelayMux {
best_bid_indices.split_first().expect("there is at least one bid");

let (best_relay, best_bid) = &bids[*best_bid_index];
let best_block_hash = best_bid.block_hash();
let best_block_hash = best_bid.message.header.block_hash();

let mut best_relays = vec![best_relay.clone()];
for bid_index in rest {
let (relay, bid) = &bids[*bid_index];
if bid.block_hash() == best_block_hash {
if bid.message.header.block_hash() == best_block_hash {
best_relays.push(relay.clone());
}
}
Expand Down Expand Up @@ -227,7 +229,10 @@ impl BlindedBlockProvider for RelayMux {
.collect::<Vec<_>>()
.await;

let expected_block_hash = signed_block.block_hash();
let block = signed_block.message();
let block_body = block.body();
let payload_header = block_body.execution_payload_header();
let expected_block_hash = payload_header.block_hash();
for (relay, response) in responses.into_iter() {
match response {
Ok(payload) => {
Expand Down
8 changes: 2 additions & 6 deletions mev-build-rs/src/reth_builder/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use ethereum_consensus::{
use ethers::signers::LocalWallet;
use mev_rs::{
signing::sign_builder_message,
types::{BidTrace, ExecutionPayload, SignedBidSubmission},
types::{BidTrace, SignedBidSubmission},
};
use reth_primitives::{Bytes, ChainSpec, SealedBlock, Withdrawal, H256, U256};
use revm::primitives::{BlockEnv, CfgEnv};
Expand All @@ -39,11 +39,7 @@ fn make_submission(
gas_used: payload.gas_used,
value: to_u256(payment),
};
let execution_payload = match to_execution_payload(payload) {
ExecutionPayload::Bellatrix(_) => unimplemented!(),
ExecutionPayload::Capella(payload) => payload,
ExecutionPayload::Deneb(_) => unimplemented!(),
};
let execution_payload = to_execution_payload(payload);
let signature = sign_builder_message(&mut message, signing_key, context)?;
Ok(SignedBidSubmission { message, execution_payload, signature })
}
Expand Down
2 changes: 1 addition & 1 deletion mev-build-rs/src/reth_builder/error.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::reth_builder::build::BuildIdentifier;
use ethereum_consensus::{primitives::Slot, state_transition::Error as ConsensusError};
use ethereum_consensus::{primitives::Slot, Error as ConsensusError};
use reth_interfaces::RethError;
use reth_primitives::H256;
use revm::primitives::EVMError;
Expand Down
4 changes: 2 additions & 2 deletions mev-build-rs/src/reth_builder/reth_compat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use ethereum_consensus::{
prelude::{ByteList, ByteVector},
},
};
use mev_rs::types::{capella, ExecutionPayload};
use mev_rs::types::ExecutionPayload;
use reth_primitives::{Bloom, SealedBlock, H160, H256, U256};

pub(crate) fn to_bytes32(value: H256) -> Bytes32 {
Expand Down Expand Up @@ -46,7 +46,7 @@ pub(crate) fn to_execution_payload(value: &SealedBlock) -> ExecutionPayload {
})
.collect::<Vec<_>>();

let payload = capella::ExecutionPayload {
let payload = spec::ExecutionPayload {
parent_hash: to_bytes32(header.parent_hash),
fee_recipient: to_bytes20(header.beneficiary),
state_root: to_bytes32(header.state_root),
Expand Down
59 changes: 28 additions & 31 deletions mev-relay-rs/src/relay.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@ use async_trait::async_trait;
use beacon_api_client::mainnet::Client;
use ethereum_consensus::{
builder::ValidatorRegistration,
capella::mainnet as capella,
clock::get_current_unix_time_in_nanos,
crypto::SecretKey,
primitives::{BlsPublicKey, Root, Slot, U256},
state_transition::Context,
};
use mev_rs::{
signing::sign_builder_message,
signing::{compute_consensus_signing_root, sign_builder_message, verify_signature},
types::{
bellatrix, capella, BidRequest, ExecutionPayload, ExecutionPayloadHeader,
SignedBlindedBeaconBlock, SignedBuilderBid, SignedValidatorRegistration,
BidRequest, BuilderBid, ExecutionPayload, ExecutionPayloadHeader, SignedBlindedBeaconBlock,
SignedBuilderBid, SignedValidatorRegistration,
},
BlindedBlockProvider, Error, ValidatorRegistry,
};
Expand Down Expand Up @@ -46,7 +47,7 @@ fn validate_execution_payload(

// TODO allow for "adjustment cap" per the protocol rules
// towards the proposer's preference
if execution_payload.gas_limit() != preferences.gas_limit {
if execution_payload.gas_limit() != &preferences.gas_limit {
return Err(Error::InvalidGasLimit)
}

Expand All @@ -65,7 +66,11 @@ fn validate_signed_block(
context: &Context,
) -> Result<(), Error> {
let local_block_hash = local_payload.block_hash();
let block_hash = signed_block.block_hash();
let mut block = signed_block.message_mut();

let body = block.body();
let payload_header = body.execution_payload_header();
let block_hash = payload_header.block_hash();
if block_hash != local_block_hash {
return Err(Error::UnknownBlock)
}
Expand All @@ -76,7 +81,11 @@ fn validate_signed_block(
// verify proposer_index is correct
// verify parent_root matches

signed_block.verify_signature(public_key, *genesis_validators_root, context).map_err(From::from)
let slot = *block.slot();
let signing_root =
compute_consensus_signing_root(&mut block, slot, genesis_validators_root, context)?;
let signature = signed_block.signature();
verify_signature(public_key, signing_root.as_ref(), signature).map_err(Into::into)
}

#[derive(Clone)]
Expand Down Expand Up @@ -170,48 +179,36 @@ impl BlindedBlockProvider for Relay {
.get_preferences(public_key)
.ok_or_else(|| Error::MissingPreferences(public_key.clone()))?;

let mut payload = ExecutionPayload::default();
let value = U256::default();

let header = {
let mut payload = ExecutionPayload::Capella(Default::default());
let mut state = self.state.lock();

validate_execution_payload(&payload, &value, &preferences)?;

let header = ExecutionPayloadHeader::try_from(&mut payload)?;
let inner = payload.capella_mut().unwrap();
let inner_header = capella::ExecutionPayloadHeader::try_from(inner)?;
let header = ExecutionPayloadHeader::Capella(inner_header);

state.execution_payloads.insert(bid_request.clone(), payload);
header
};

match header {
ExecutionPayloadHeader::Bellatrix(header) => {
let mut bid =
bellatrix::BuilderBid { header, value, public_key: self.public_key.clone() };
let signature = sign_builder_message(&mut bid, &self.secret_key, &self.context)?;

let signed_bid = bellatrix::SignedBuilderBid { message: bid, signature };
Ok(SignedBuilderBid::Bellatrix(signed_bid))
}
ExecutionPayloadHeader::Capella(header) => {
let mut bid =
capella::BuilderBid { header, value, public_key: self.public_key.clone() };
let signature = sign_builder_message(&mut bid, &self.secret_key, &self.context)?;

let signed_bid = capella::SignedBuilderBid { message: bid, signature };
Ok(SignedBuilderBid::Capella(signed_bid))
}
ExecutionPayloadHeader::Deneb(_header) => unimplemented!(),
}
let mut bid = BuilderBid { header, value, public_key: self.public_key.clone() };
let signature = sign_builder_message(&mut bid, &self.secret_key, &self.context)?;
Ok(SignedBuilderBid { message: bid, signature })
}

async fn open_bid(
&self,
signed_block: &mut SignedBlindedBeaconBlock,
) -> Result<ExecutionPayload, Error> {
let slot = signed_block.slot();
let parent_hash = signed_block.parent_hash().clone();
let proposer_index = signed_block.proposer_index();
let block = signed_block.message();
let slot = *block.slot();
let body = block.body();
let payload_header = body.execution_payload_header();
let parent_hash = payload_header.parent_hash().clone();
let proposer_index = *block.proposer_index();
let public_key =
self.validator_registry.get_public_key(proposer_index).map_err(Error::from)?;
let bid_request = BidRequest { slot, parent_hash, public_key };
Expand Down
4 changes: 2 additions & 2 deletions mev-rs/src/blinded_block_provider/api/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ impl Client {
let result: ApiResult<VersionedValue<SignedBuilderBid>> =
response.json().await.map_err(beacon_api_client::Error::Http)?;
match result {
ApiResult::Ok(result) => Ok(result.payload),
ApiResult::Ok(result) => Ok(result.data),
ApiResult::Err(err) => Err(Error::Api(err.into())),
}
}
Expand All @@ -79,7 +79,7 @@ impl Client {
let result: ApiResult<VersionedValue<ExecutionPayload>> =
response.json().await.map_err(beacon_api_client::Error::Http)?;
match result {
ApiResult::Ok(result) => Ok(result.payload),
ApiResult::Ok(result) => Ok(result.data),
ApiResult::Err(err) => Err(ApiError::from(err).into()),
}
}
Expand Down
29 changes: 9 additions & 20 deletions mev-rs/src/blinded_block_provider/api/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use crate::{
blinded_block_provider::BlindedBlockProvider,
error::Error,
types::{
bellatrix, capella, deneb, BidRequest, ExecutionPayload, SignedBlindedBeaconBlock,
SignedBuilderBid, SignedValidatorRegistration,
BidRequest, ExecutionPayload, SignedBlindedBeaconBlock, SignedBuilderBid,
SignedValidatorRegistration,
},
};
use axum::{
Expand All @@ -13,9 +13,8 @@ use axum::{
routing::{get, post, IntoMakeService},
Router,
};
use beacon_api_client::{Error as ApiClientError, VersionedValue};
use beacon_api_client::VersionedValue;
use hyper::server::conn::AddrIncoming;
use serde::Deserialize;
use std::net::{Ipv4Addr, SocketAddr};
use tokio::task::JoinHandle;

Expand All @@ -41,31 +40,21 @@ async fn handle_fetch_bid<B: BlindedBlockProvider>(
) -> Result<Json<VersionedValue<SignedBuilderBid>>, Error> {
let signed_bid = builder.fetch_best_bid(&bid_request).await?;
tracing::info!("returning bid with {signed_bid} for bid request at {bid_request}");
let response = VersionedValue { payload: signed_bid, meta: Default::default() };
let version = signed_bid.version();
let response = VersionedValue { version, data: signed_bid, meta: Default::default() };
Ok(Json(response))
}

async fn handle_open_bid<B: BlindedBlockProvider>(
State(builder): State<B>,
Json(block): Json<serde_json::Value>,
Json(mut block): Json<SignedBlindedBeaconBlock>,
) -> Result<Json<VersionedValue<ExecutionPayload>>, Error> {
let mut block = deneb::SignedBlindedBlockAndBlobSidecars::deserialize(&block)
.map(SignedBlindedBeaconBlock::Deneb)
.or_else(|_| {
capella::SignedBlindedBeaconBlock::deserialize(&block)
.map(SignedBlindedBeaconBlock::Capella)
})
.or_else(|_| {
bellatrix::SignedBlindedBeaconBlock::deserialize(&block)
.map(SignedBlindedBeaconBlock::Bellatrix)
})
.map_err(ApiClientError::from)?;

let payload = builder.open_bid(&mut block).await?;
let block_hash = payload.block_hash();
let slot = block.slot();
let slot = *block.message().slot();
tracing::info!("returning provided payload in slot {slot} with block_hash {block_hash}");
let response = VersionedValue { payload, meta: Default::default() };
let version = payload.version();
let response = VersionedValue { version, data: payload, meta: Default::default() };
Ok(Json(response))
}

Expand Down
2 changes: 1 addition & 1 deletion mev-rs/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::types::BidRequest;
use beacon_api_client::Error as ApiError;
use ethereum_consensus::{
primitives::{BlsPublicKey, ExecutionAddress, Hash32, Slot},
state_transition::Error as ConsensusError,
Error as ConsensusError,
};
use thiserror::Error;

Expand Down
53 changes: 28 additions & 25 deletions mev-rs/src/signing.rs
Original file line number Diff line number Diff line change
@@ -1,46 +1,49 @@
pub use ethereum_consensus::signing::{compute_signing_root, verify_signature};
use ethereum_consensus::{
builder::compute_builder_domain,
crypto::SecretKey,
domains::DomainType,
phase0::mainnet::compute_domain,
primitives::{BlsPublicKey, BlsSignature, Root, Slot},
signing::{sign_with_domain, verify_signed_data},
ssz::prelude::SimpleSerialize,
state_transition::{Context, Error},
Fork,
primitives::{BlsSignature, Root, Slot},
signing::sign_with_domain,
ssz::prelude::Merkleized,
state_transition::Context,
Error, Fork,
};
pub use ethereum_consensus::{
crypto::SecretKey,
signing::{compute_signing_root, verify_signature},
};

pub fn verify_signed_consensus_message<T: SimpleSerialize>(
message: &mut T,
signature: &BlsSignature,
public_key: &BlsPublicKey,
pub fn compute_consensus_signing_root<T: Merkleized>(
data: &mut T,
slot: Slot,
genesis_validators_root: &Root,
context: &Context,
slot_hint: Option<Slot>,
root_hint: Option<Root>,
) -> Result<(), Error> {
let fork_version = slot_hint.map(|slot| match context.fork_for(slot) {
) -> Result<Root, Error> {
let fork_version = match context.fork_for(slot) {
Fork::Bellatrix => context.bellatrix_fork_version,
Fork::Capella => context.capella_fork_version,
_ => unimplemented!(),
});
let domain =
compute_domain(DomainType::BeaconProposer, fork_version, root_hint, context).unwrap();
verify_signed_data(message, signature, public_key, domain)?;
Ok(())
Fork::Deneb => context.deneb_fork_version,
_ => unimplemented!("fork not supported"),
};
let domain = compute_domain(
DomainType::BeaconProposer,
Some(fork_version),
Some(*genesis_validators_root),
context,
)?;
compute_signing_root(data, domain)
}

pub fn sign_builder_message<T: SimpleSerialize>(
pub fn sign_builder_message<T: Merkleized>(
message: &mut T,
signing_key: &SecretKey,
context: &Context,
) -> Result<BlsSignature, Error> {
let domain = compute_builder_domain(context)?;
let signature = sign_with_domain(message, signing_key, domain)?;
Ok(signature)
sign_with_domain(message, signing_key, domain)
}

pub fn compute_builder_signing_root<T: SimpleSerialize>(
pub fn compute_builder_signing_root<T: Merkleized>(
data: &mut T,
context: &Context,
) -> Result<Root, Error> {
Expand Down
Loading

0 comments on commit f848936

Please sign in to comment.