Skip to content

Commit

Permalink
Merge pull request #151 from ralexstokes/poly2
Browse files Browse the repository at this point in the history
uses polymorphic types
  • Loading branch information
ralexstokes authored Oct 16, 2023
2 parents 6abbac2 + d2b43c7 commit 1128475
Show file tree
Hide file tree
Showing 22 changed files with 750 additions and 1,158 deletions.
791 changes: 384 additions & 407 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ default-members = ["bin/mev"]
version = "0.3.0"

[workspace.dependencies]
ethereum-consensus = { git = "https://github.com/ralexstokes/ethereum-consensus", rev = "afbf74216b49d30562aa3e966b9daa9aa416d534" }
beacon-api-client = { git = "https://github.com/ralexstokes/ethereum-consensus", rev = "afbf74216b49d30562aa3e966b9daa9aa416d534" }
ethereum-consensus = { git = "https://github.com/ralexstokes/ethereum-consensus", rev = "e810cecbb113de66aeedae6dcde2a69cd284f88d" }
beacon-api-client = { git = "https://github.com/ralexstokes/ethereum-consensus", rev = "e810cecbb113de66aeedae6dcde2a69cd284f88d" }

reth-payload-builder = { git = "https://github.com/paradigmxyz/reth", rev = "1b16d804ef01f4ec3c25e7986381c22739c105b9" }
reth-primitives = { git = "https://github.com/paradigmxyz/reth", rev = "1b16d804ef01f4ec3c25e7986381c22739c105b9" }
Expand Down
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
105 changes: 105 additions & 0 deletions mev-boost-rs/tests/identity_builder.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
use async_trait::async_trait;
use ethereum_consensus::{
bellatrix::mainnet as bellatrix,
builder::{SignedValidatorRegistration, ValidatorRegistration},
capella::mainnet as capella,
crypto::SecretKey,
primitives::{BlsPublicKey, Slot, U256},
state_transition::Context,
};
use mev_rs::{
blinded_block_provider::BlindedBlockProvider,
signing::sign_builder_message,
types::{
BidRequest, BuilderBid, ExecutionPayload, ExecutionPayloadHeader, SignedBlindedBeaconBlock,
SignedBuilderBid,
},
Error,
};
use std::{
collections::HashMap,
sync::{Arc, Mutex},
};

#[derive(Default, Clone)]
pub struct IdentityBuilder {
signing_key: SecretKey,
public_key: BlsPublicKey,
context: Arc<Context>,
bids: Arc<Mutex<HashMap<Slot, ExecutionPayload>>>,
registrations: Arc<Mutex<HashMap<BlsPublicKey, ValidatorRegistration>>>,
}

impl IdentityBuilder {
pub fn new(context: Context) -> Self {
let signing_key = SecretKey::try_from([1u8; 32].as_ref()).unwrap();
let public_key = signing_key.public_key();
Self { signing_key, public_key, context: Arc::new(context), ..Default::default() }
}
}

#[async_trait]
impl BlindedBlockProvider for IdentityBuilder {
async fn register_validators(
&self,
registrations: &mut [SignedValidatorRegistration],
) -> Result<(), Error> {
let mut state = self.registrations.lock().unwrap();
for registration in registrations {
let registration = &registration.message;
let public_key = registration.public_key.clone();
state.insert(public_key, registration.clone());
}
Ok(())
}

async fn fetch_best_bid(
&self,
BidRequest { slot, parent_hash, public_key }: &BidRequest,
) -> Result<SignedBuilderBid, Error> {
let capella_fork_slot = self.context.capella_fork_epoch * self.context.slots_per_epoch;
let state = self.registrations.lock().unwrap();
let preferences = state.get(public_key).unwrap();
let value = U256::from(1337);
let (payload, header) = if *slot < capella_fork_slot {
let mut payload = bellatrix::ExecutionPayload {
parent_hash: parent_hash.clone(),
fee_recipient: preferences.fee_recipient.clone(),
gas_limit: preferences.gas_limit,
..Default::default()
};
let header = ExecutionPayloadHeader::Bellatrix(
bellatrix::ExecutionPayloadHeader::try_from(&mut payload).unwrap(),
);
(ExecutionPayload::Bellatrix(payload), header)
} else {
let mut payload = capella::ExecutionPayload {
parent_hash: parent_hash.clone(),
fee_recipient: preferences.fee_recipient.clone(),
gas_limit: preferences.gas_limit,
..Default::default()
};
let header = ExecutionPayloadHeader::Capella(
capella::ExecutionPayloadHeader::try_from(&mut payload).unwrap(),
);
(ExecutionPayload::Capella(payload), header)
};

let mut builder_bid = BuilderBid { header, value, public_key: self.public_key.clone() };
let signature =
sign_builder_message(&mut builder_bid, &self.signing_key, &self.context).unwrap();
let signed_builder_bid = SignedBuilderBid { message: builder_bid, signature };
let mut state = self.bids.lock().unwrap();
state.insert(*slot, payload);
Ok(signed_builder_bid)
}

async fn open_bid(
&self,
signed_block: &mut SignedBlindedBeaconBlock,
) -> Result<ExecutionPayload, Error> {
let slot = *signed_block.message().slot();
let state = self.bids.lock().unwrap();
Ok(state.get(&slot).cloned().unwrap())
}
}
151 changes: 23 additions & 128 deletions mev-boost-rs/tests/integration.rs
Original file line number Diff line number Diff line change
@@ -1,30 +1,27 @@
use async_trait::async_trait;
mod identity_builder;

use beacon_api_client::Client as ApiClient;
use ethereum_consensus::{
bellatrix::mainnet as bellatrix,
builder::{SignedValidatorRegistration, ValidatorRegistration},
capella::mainnet as capella,
crypto::SecretKey,
phase0::mainnet::{compute_domain, Validator},
primitives::{BlsPublicKey, DomainType, ExecutionAddress, Hash32, Root, Slot, U256},
primitives::{DomainType, ExecutionAddress, Hash32, Root},
signing::sign_with_domain,
state_transition::{Context, Forks},
state_transition::Context,
Fork,
};
use identity_builder::*;
use mev_boost_rs::{Config, Service};
use mev_rs::{
blinded_block_provider::{BlindedBlockProvider, Client as RelayClient, Server as RelayServer},
blinded_block_provider::{Client as RelayClient, Server as RelayServer},
signing::sign_builder_message,
types::{
bellatrix as bellatrix_builder, capella as capella_builder, BidRequest, ExecutionPayload,
SignedBlindedBeaconBlock, SignedBuilderBid,
},
Error,
types::{BidRequest, SignedBlindedBeaconBlock},
};
use rand::seq::SliceRandom;
use std::{
collections::HashMap,
net::Ipv4Addr,
sync::{Arc, Mutex},
time::{SystemTime, UNIX_EPOCH},
};
use url::Url;
Expand Down Expand Up @@ -67,96 +64,6 @@ fn create_proposers<R: rand::Rng>(rng: &mut R, count: usize) -> Vec<Proposer> {
.collect()
}

#[derive(Default, Clone)]
pub struct IdentityBuilder {
signing_key: SecretKey,
public_key: BlsPublicKey,
context: Arc<Context>,
bids: Arc<Mutex<HashMap<Slot, ExecutionPayload>>>,
registrations: Arc<Mutex<HashMap<BlsPublicKey, ValidatorRegistration>>>,
}

impl IdentityBuilder {
fn new(context: Context) -> Self {
let signing_key = SecretKey::try_from([1u8; 32].as_ref()).unwrap();
let public_key = signing_key.public_key();
Self { signing_key, public_key, context: Arc::new(context), ..Default::default() }
}
}

#[async_trait]
impl BlindedBlockProvider for IdentityBuilder {
async fn register_validators(
&self,
registrations: &mut [SignedValidatorRegistration],
) -> Result<(), Error> {
let mut state = self.registrations.lock().unwrap();
for registration in registrations {
let registration = &registration.message;
let public_key = registration.public_key.clone();
state.insert(public_key, registration.clone());
}
Ok(())
}

async fn fetch_best_bid(
&self,
BidRequest { slot, parent_hash, public_key }: &BidRequest,
) -> Result<SignedBuilderBid, Error> {
let capella_fork_slot = self.context.capella_fork_epoch * self.context.slots_per_epoch;
let state = self.registrations.lock().unwrap();
let preferences = state.get(public_key).unwrap();
let value = U256::from(1337);
let (payload, signed_builder_bid) = if *slot < capella_fork_slot {
let mut inner = bellatrix::ExecutionPayload {
parent_hash: parent_hash.clone(),
fee_recipient: preferences.fee_recipient.clone(),
gas_limit: preferences.gas_limit,
..Default::default()
};
let header = bellatrix::ExecutionPayloadHeader::try_from(&mut inner).unwrap();
let payload = ExecutionPayload::Bellatrix(inner);
let mut inner = bellatrix_builder::BuilderBid {
header,
value,
public_key: self.public_key.clone(),
};
let signature =
sign_builder_message(&mut inner, &self.signing_key, &self.context).unwrap();
let inner = bellatrix_builder::SignedBuilderBid { message: inner, signature };
(payload, SignedBuilderBid::Bellatrix(inner))
} else {
let mut inner = capella::ExecutionPayload {
parent_hash: parent_hash.clone(),
fee_recipient: preferences.fee_recipient.clone(),
gas_limit: preferences.gas_limit,
..Default::default()
};
let header = capella::ExecutionPayloadHeader::try_from(&mut inner).unwrap();
let payload = ExecutionPayload::Capella(inner);
let mut inner =
capella_builder::BuilderBid { header, value, public_key: self.public_key.clone() };
let signature =
sign_builder_message(&mut inner, &self.signing_key, &self.context).unwrap();
let inner = capella_builder::SignedBuilderBid { message: inner, signature };
(payload, SignedBuilderBid::Capella(inner))
};

let mut state = self.bids.lock().unwrap();
state.insert(*slot, payload);
Ok(signed_builder_bid)
}

async fn open_bid(
&self,
signed_block: &mut SignedBlindedBeaconBlock,
) -> Result<ExecutionPayload, Error> {
let slot = signed_block.slot();
let state = self.bids.lock().unwrap();
Ok(state.get(&slot).cloned().unwrap())
}
}

#[tokio::test]
async fn test_end_to_end() {
setup_logging();
Expand Down Expand Up @@ -231,10 +138,10 @@ async fn propose_block(
context: &Context,
genesis_validators_root: &Root,
) {
let fork = if shuffling_index == 0 { Forks::Bellatrix } else { Forks::Capella };
let fork = if shuffling_index == 0 { Fork::Bellatrix } else { Fork::Capella };
let current_slot = match fork {
Forks::Bellatrix => 32 + context.bellatrix_fork_epoch * context.slots_per_epoch,
Forks::Capella => 32 + context.capella_fork_epoch * context.slots_per_epoch,
Fork::Bellatrix => 32 + context.bellatrix_fork_epoch * context.slots_per_epoch,
Fork::Capella => 32 + context.capella_fork_epoch * context.slots_per_epoch,
_ => unimplemented!(),
};
let parent_hash = Hash32::try_from([shuffling_index as u8; 32].as_ref()).unwrap();
Expand All @@ -245,17 +152,14 @@ async fn propose_block(
public_key: proposer.validator.public_key.clone(),
};
let signed_bid = beacon_node.fetch_best_bid(&request).await.unwrap();
let bid_parent_hash = signed_bid.parent_hash();
let bid_parent_hash = signed_bid.message.header.parent_hash();
assert_eq!(bid_parent_hash, &parent_hash);

let signed_block = match fork {
Forks::Bellatrix => {
let bid = match signed_bid {
SignedBuilderBid::Bellatrix(bid) => bid,
_ => unimplemented!(),
};
Fork::Bellatrix => {
let header = signed_bid.message.header.bellatrix().unwrap().clone();
let beacon_block_body = bellatrix::BlindedBeaconBlockBody {
execution_payload_header: bid.message.header,
execution_payload_header: header,
..Default::default()
};
let mut beacon_block = bellatrix::BlindedBeaconBlock {
Expand All @@ -278,13 +182,10 @@ async fn propose_block(
bellatrix::SignedBlindedBeaconBlock { message: beacon_block, signature };
SignedBlindedBeaconBlock::Bellatrix(signed_block)
}
Forks::Capella => {
let bid = match signed_bid {
SignedBuilderBid::Capella(bid) => bid,
_ => unimplemented!(),
};
Fork::Capella => {
let header = signed_bid.message.header.capella().unwrap().clone();
let beacon_block_body = capella::BlindedBeaconBlockBody {
execution_payload_header: bid.message.header,
execution_payload_header: header,
..Default::default()
};
let mut beacon_block = capella::BlindedBeaconBlock {
Expand Down Expand Up @@ -314,17 +215,11 @@ async fn propose_block(

let payload = beacon_node.open_bid(&signed_block).await.unwrap();

match payload {
ExecutionPayload::Bellatrix(payload) => {
assert_eq!(payload.parent_hash, parent_hash);
assert_eq!(payload.fee_recipient, proposer.fee_recipient);
}
ExecutionPayload::Capella(payload) => {
assert_eq!(payload.parent_hash, parent_hash);
assert_eq!(payload.fee_recipient, proposer.fee_recipient);
}
_ => unimplemented!(),
}
let payload_parent_hash = payload.parent_hash();
assert_eq!(payload_parent_hash, &parent_hash);

let payload_fee_recipient = payload.fee_recipient();
assert_eq!(payload_fee_recipient, &proposer.fee_recipient);

beacon_node.check_status().await.unwrap();
}
Loading

0 comments on commit 1128475

Please sign in to comment.