-
Notifications
You must be signed in to change notification settings - Fork 76
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
wip: refactor to start cleaning things up
- Loading branch information
1 parent
445f580
commit 6dd6927
Showing
11 changed files
with
493 additions
and
406 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,200 @@ | ||
use crate::mempool_builder::builder::{Error, RelayIndex}; | ||
use ethereum_consensus::{ | ||
capella::mainnet as spec, | ||
crypto::{hash, SecretKey}, | ||
primitives::{BlsPublicKey, Bytes32, ExecutionAddress, Slot}, | ||
ssz::{ByteList, ByteVector}, | ||
state_transition::Context, | ||
}; | ||
use ethers::signers::LocalWallet; | ||
use mev_rs::{ | ||
signing::sign_builder_message, | ||
types::{capella, BidTrace, ExecutionPayload, SignedBidSubmission}, | ||
}; | ||
use reth_primitives::{Bloom, Bytes, ChainSpec, SealedBlock, Withdrawal, H160, H256, U256}; | ||
use revm::primitives::{BlockEnv, CfgEnv}; | ||
use ssz_rs::prelude::*; | ||
use std::sync::{Arc, Mutex}; | ||
|
||
pub type BuildIdentifier = Bytes32; | ||
|
||
fn to_bytes32(value: H256) -> Bytes32 { | ||
Bytes32::try_from(value.as_bytes()).unwrap() | ||
} | ||
|
||
fn to_bytes20(value: H160) -> ExecutionAddress { | ||
ExecutionAddress::try_from(value.as_bytes()).unwrap() | ||
} | ||
|
||
fn to_byte_vector(value: Bloom) -> ByteVector<256> { | ||
ByteVector::<256>::try_from(value.as_bytes()).unwrap() | ||
} | ||
|
||
fn to_u256(value: &U256) -> ssz_rs::U256 { | ||
ssz_rs::U256::try_from_bytes_le(&value.to_le_bytes::<32>()).unwrap() | ||
} | ||
|
||
fn to_execution_payload(value: &SealedBlock) -> ExecutionPayload { | ||
let hash = value.hash(); | ||
let header = &value.header; | ||
let transactions = &value.body; | ||
let withdrawals = &value.withdrawals; | ||
let transactions = transactions | ||
.iter() | ||
.map(|t| spec::Transaction::try_from(t.envelope_encoded().as_ref()).unwrap()) | ||
.collect::<Vec<_>>(); | ||
let withdrawals = withdrawals | ||
.as_ref() | ||
.unwrap() | ||
.iter() | ||
.map(|w| spec::Withdrawal { | ||
index: w.index as usize, | ||
validator_index: w.validator_index as usize, | ||
address: to_bytes20(w.address), | ||
amount: w.amount, | ||
}) | ||
.collect::<Vec<_>>(); | ||
|
||
let payload = capella::ExecutionPayload { | ||
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(hash), | ||
transactions: TryFrom::try_from(transactions).unwrap(), | ||
withdrawals: TryFrom::try_from(withdrawals).unwrap(), | ||
}; | ||
ExecutionPayload::Capella(payload) | ||
} | ||
|
||
fn make_submission( | ||
signing_key: &SecretKey, | ||
builder_public_key: &BlsPublicKey, | ||
context: &Context, | ||
build_context: &BuildContext, | ||
payload: &SealedBlock, | ||
payment: &U256, | ||
) -> Result<SignedBidSubmission, Error> { | ||
let mut message = BidTrace { | ||
slot: build_context.slot, | ||
parent_hash: to_bytes32(payload.parent_hash), | ||
block_hash: to_bytes32(payload.hash), | ||
builder_public_key: builder_public_key.clone(), | ||
proposer_public_key: build_context.proposer.clone(), | ||
proposer_fee_recipient: build_context.proposer_fee_recipient.clone(), | ||
gas_limit: payload.gas_limit, | ||
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 signature = sign_builder_message(&mut message, signing_key, context)?; | ||
Ok(SignedBidSubmission { message, execution_payload, signature }) | ||
} | ||
|
||
#[derive(Debug, Clone)] | ||
pub struct BuildContext { | ||
pub slot: Slot, | ||
pub parent_hash: H256, | ||
pub proposer: BlsPublicKey, | ||
pub timestamp: u64, | ||
pub proposer_fee_recipient: ExecutionAddress, | ||
pub prev_randao: H256, | ||
pub withdrawals: Vec<Withdrawal>, | ||
pub relays: Vec<RelayIndex>, | ||
pub chain_spec: Arc<ChainSpec>, | ||
pub block_env: BlockEnv, | ||
pub cfg_env: CfgEnv, | ||
pub extra_data: Bytes, | ||
pub parent_block: Arc<SealedBlock>, | ||
pub builder_wallet: LocalWallet, | ||
// Amount of gas to reserve after building a payload | ||
// e.g. used for end-of-block proposer payments | ||
pub gas_reserve: u64, | ||
// Amount of the block's value to bid to the proposer | ||
pub bid_percent: f64, | ||
// Amount to add to the block's value to bid to the proposer | ||
pub subsidy: U256, | ||
} | ||
|
||
pub fn compute_build_id(slot: Slot, parent_hash: H256, proposer: &BlsPublicKey) -> BuildIdentifier { | ||
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"); | ||
hash(data) | ||
} | ||
|
||
impl BuildContext { | ||
pub fn id(&self) -> BuildIdentifier { | ||
compute_build_id(self.slot, self.parent_hash, &self.proposer) | ||
} | ||
|
||
pub fn base_fee(&self) -> u64 { | ||
self.block_env.basefee.to::<u64>() | ||
} | ||
|
||
pub fn number(&self) -> u64 { | ||
self.block_env.number.to::<u64>() | ||
} | ||
|
||
pub fn gas_limit(&self) -> u64 { | ||
self.block_env.gas_limit.try_into().unwrap_or(u64::MAX) | ||
} | ||
} | ||
|
||
#[derive(Debug)] | ||
pub struct Build { | ||
pub context: BuildContext, | ||
pub state: Mutex<State>, | ||
} | ||
|
||
type State = PayloadWithPayments; | ||
|
||
impl Build { | ||
pub fn new(context: BuildContext, payload_with_payments: PayloadWithPayments) -> Self { | ||
Self { context, state: Mutex::new(payload_with_payments) } | ||
} | ||
|
||
pub fn value(&self) -> U256 { | ||
let state = self.state.lock().unwrap(); | ||
state.proposer_payment | ||
} | ||
|
||
pub fn prepare_bid( | ||
&self, | ||
secret_key: &SecretKey, | ||
public_key: &BlsPublicKey, | ||
context: &Context, | ||
) -> Result<(SignedBidSubmission, U256), Error> { | ||
let build_context = &self.context; | ||
let state = self.state.lock().unwrap(); | ||
let payload = &state.payload; | ||
let payment = &state.proposer_payment; | ||
let builder_payment = state.builder_payment; | ||
Ok(( | ||
make_submission(secret_key, public_key, context, build_context, payload, payment)?, | ||
builder_payment, | ||
)) | ||
} | ||
} | ||
|
||
#[derive(Debug)] | ||
pub struct PayloadWithPayments { | ||
// TODO: refactor here to `Option<_>` | ||
// can migrate to "take" pattern and minimize lock contention | ||
pub payload: SealedBlock, | ||
pub proposer_payment: U256, | ||
pub builder_payment: U256, | ||
} |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.