From bda21106253e2aa0f35c94013442e60e500d6d5f Mon Sep 17 00:00:00 2001 From: jacobkaufmann Date: Fri, 26 Apr 2024 16:59:51 -0600 Subject: [PATCH 1/2] feat: add deneb compatibility --- mev-build-rs/src/auctioneer.rs | 23 +++++- mev-relay-rs/src/relay.rs | 15 ++-- mev-rs/src/types/auction_contents.rs | 2 +- mev-rs/src/types/block_submission.rs | 108 +++++++++++++++++++++++++-- mev-rs/src/types/mod.rs | 6 +- 5 files changed, 133 insertions(+), 21 deletions(-) diff --git a/mev-build-rs/src/auctioneer.rs b/mev-build-rs/src/auctioneer.rs index 3c071514..a6a7656d 100644 --- a/mev-build-rs/src/auctioneer.rs +++ b/mev-build-rs/src/auctioneer.rs @@ -10,11 +10,12 @@ use ethereum_consensus::{ crypto::SecretKey, primitives::{BlsPublicKey, Epoch, Slot}, state_transition::Context, + Fork, }; use mev_rs::{ relay::parse_relay_endpoints, signing::sign_builder_message, - types::{BidTrace, SignedBidSubmission}, + types::{block_submission, BidTrace, SignedBidSubmission}, BlindedBlockRelayer, Relay, }; use reth::{ @@ -50,7 +51,25 @@ fn prepare_submission( }; let execution_payload = to_execution_payload(payload.block()); let signature = sign_builder_message(&message, signing_key, context)?; - Ok(SignedBidSubmission { message, execution_payload, signature }) + let submission = match execution_payload.version() { + Fork::Bellatrix => { + SignedBidSubmission::Bellatrix(block_submission::bellatrix::SignedBidSubmission { + message, + execution_payload, + signature, + }) + } + Fork::Capella => { + SignedBidSubmission::Capella(block_submission::capella::SignedBidSubmission { + message, + execution_payload, + signature, + }) + } + Fork::Deneb => unimplemented!(), + other => unreachable!("fork {other} is not reachable from this type"), + }; + Ok(submission) } #[derive(Deserialize, Debug, Default, Clone)] diff --git a/mev-relay-rs/src/relay.rs b/mev-relay-rs/src/relay.rs index bc42e36e..8b9c86c5 100644 --- a/mev-relay-rs/src/relay.rs +++ b/mev-relay-rs/src/relay.rs @@ -593,7 +593,7 @@ impl BlindedBlockRelayer for Relay { async fn submit_bid(&self, signed_submission: &SignedBidSubmission) -> Result<(), Error> { let (auction_request, value, builder_public_key) = { - let bid_trace = &signed_submission.message; + let bid_trace = signed_submission.message(); let builder_public_key = &bid_trace.builder_public_key; self.validate_allowed_builder(builder_public_key)?; @@ -604,20 +604,17 @@ impl BlindedBlockRelayer for Relay { }; self.validate_auction_request(&auction_request)?; - self.validate_builder_submission_trusted( - bid_trace, - &signed_submission.execution_payload, - )?; + self.validate_builder_submission_trusted(bid_trace, signed_submission.payload())?; debug!(%auction_request, "validated builder submission"); (auction_request, bid_trace.value, bid_trace.builder_public_key.clone()) }; - let message = &signed_submission.message; - let public_key = &signed_submission.message.builder_public_key; - let signature = &signed_submission.signature; + let message = signed_submission.message(); + let public_key = &signed_submission.message().builder_public_key; + let signature = signed_submission.signature(); verify_signed_builder_data(message, public_key, signature, &self.context)?; - let execution_payload = signed_submission.execution_payload.clone(); + let execution_payload = signed_submission.payload().clone(); // NOTE: this does _not_ respect cancellations // TODO: move to regime where we track best bid by builder // and also move logic to cursor best bid for auction off this API diff --git a/mev-rs/src/types/auction_contents.rs b/mev-rs/src/types/auction_contents.rs index acccca85..fc4889f4 100644 --- a/mev-rs/src/types/auction_contents.rs +++ b/mev-rs/src/types/auction_contents.rs @@ -21,7 +21,7 @@ pub mod deneb { ssz::prelude::*, }; - #[derive(Debug)] + #[derive(Clone, Debug, Serializable, HashTreeRoot)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct BlobsBundle { commitments: List, diff --git a/mev-rs/src/types/block_submission.rs b/mev-rs/src/types/block_submission.rs index c56cb036..eaea2ce1 100644 --- a/mev-rs/src/types/block_submission.rs +++ b/mev-rs/src/types/block_submission.rs @@ -1,7 +1,8 @@ -use crate::types::ExecutionPayload; +use crate::types::{auction_contents::deneb::BlobsBundle, ExecutionPayload}; use ethereum_consensus::{ primitives::{BlsPublicKey, BlsSignature, ExecutionAddress, Hash32, Slot}, ssz::prelude::*, + Fork, }; #[derive(Debug, Default, Clone, SimpleSerialize)] @@ -24,10 +25,105 @@ pub struct BidTrace { pub value: U256, } +pub mod bellatrix { + use super::{BidTrace, BlsSignature, ExecutionPayload}; + use ethereum_consensus::ssz::prelude::*; + + #[derive(Debug, Clone, Serializable, HashTreeRoot)] + #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] + pub struct SignedBidSubmission { + pub message: BidTrace, + pub execution_payload: ExecutionPayload, + pub signature: BlsSignature, + } +} + +pub mod capella { + pub use super::bellatrix::*; +} + +pub mod deneb { + use super::{BidTrace, BlsSignature, ExecutionPayload}; + use crate::types::auction_contents::deneb::BlobsBundle; + use ethereum_consensus::ssz::prelude::*; + + #[derive(Debug, Clone, Serializable, HashTreeRoot)] + #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] + pub struct SignedBidSubmission { + pub message: BidTrace, + pub execution_payload: ExecutionPayload, + pub blobs_bundle: BlobsBundle, + pub signature: BlsSignature, + } +} + #[derive(Debug, Clone, Serializable, HashTreeRoot)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub struct SignedBidSubmission { - pub message: BidTrace, - pub execution_payload: ExecutionPayload, - pub signature: BlsSignature, +#[cfg_attr(feature = "serde", derive(serde::Serialize))] +#[serde(untagged)] +#[ssz(transparent)] +pub enum SignedBidSubmission { + Bellatrix(bellatrix::SignedBidSubmission), + Capella(capella::SignedBidSubmission), + Deneb(deneb::SignedBidSubmission), +} + +impl<'de> serde::Deserialize<'de> for SignedBidSubmission { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let value = serde_json::Value::deserialize(deserializer)?; + if let Ok(inner) = <_ as serde::Deserialize>::deserialize(&value) { + return Ok(Self::Deneb(inner)) + } + if let Ok(inner) = <_ as serde::Deserialize>::deserialize(&value) { + return Ok(Self::Capella(inner)) + } + if let Ok(inner) = <_ as serde::Deserialize>::deserialize(&value) { + return Ok(Self::Bellatrix(inner)) + } + Err(serde::de::Error::custom("no variant could be deserialized from input")) + } +} + +impl SignedBidSubmission { + pub fn version(&self) -> Fork { + match self { + Self::Bellatrix(..) => Fork::Bellatrix, + Self::Capella(..) => Fork::Capella, + Self::Deneb(..) => Fork::Deneb, + } + } + + pub fn message(&self) -> &BidTrace { + match self { + Self::Bellatrix(inner) => &inner.message, + Self::Capella(inner) => &inner.message, + Self::Deneb(inner) => &inner.message, + } + } + + pub fn payload(&self) -> &ExecutionPayload { + match self { + Self::Bellatrix(inner) => &inner.execution_payload, + Self::Capella(inner) => &inner.execution_payload, + Self::Deneb(inner) => &inner.execution_payload, + } + } + + pub fn signature(&self) -> &BlsSignature { + match self { + Self::Bellatrix(inner) => &inner.signature, + Self::Capella(inner) => &inner.signature, + Self::Deneb(inner) => &inner.signature, + } + } + + pub fn blobs_bundle(&self) -> Option<&BlobsBundle> { + match self { + Self::Bellatrix(..) => None, + Self::Capella(..) => None, + Self::Deneb(inner) => Some(&inner.blobs_bundle), + } + } } diff --git a/mev-rs/src/types/mod.rs b/mev-rs/src/types/mod.rs index 52f6114d..6917db14 100644 --- a/mev-rs/src/types/mod.rs +++ b/mev-rs/src/types/mod.rs @@ -1,12 +1,12 @@ mod auction_contents; mod auction_request; -mod block_submission; +pub mod block_submission; pub mod builder_bid; mod proposer_schedule; -pub use auction_contents::*; +pub use auction_contents::AuctionContents; pub use auction_request::*; -pub use block_submission::*; +pub use block_submission::{BidTrace, SignedBidSubmission}; pub use builder_bid::{BuilderBid, SignedBuilderBid}; pub use ethereum_consensus::{ builder::SignedValidatorRegistration, From 5eb94dd83443716d1084f59d48af06535602c51b Mon Sep 17 00:00:00 2001 From: jacobkaufmann Date: Mon, 29 Apr 2024 13:11:51 -0600 Subject: [PATCH 2/2] add blob bundle compat/conversion --- mev-build-rs/src/auctioneer.rs | 11 ++++++++-- mev-build-rs/src/utils/compat.rs | 32 ++++++++++++++++++++++------ mev-rs/src/types/auction_contents.rs | 6 +++--- mev-rs/src/types/mod.rs | 2 +- 4 files changed, 39 insertions(+), 12 deletions(-) diff --git a/mev-build-rs/src/auctioneer.rs b/mev-build-rs/src/auctioneer.rs index a6a7656d..8049a80d 100644 --- a/mev-build-rs/src/auctioneer.rs +++ b/mev-build-rs/src/auctioneer.rs @@ -3,7 +3,7 @@ use crate::{ bidder::{AuctionContext, BidRequest, DeadlineBidder}, builder::{KeepAlive, Message as BuilderMessage}, service::ClockMessage, - utils::compat::{to_bytes32, to_execution_payload}, + utils::compat::{to_blobs_bundle, to_bytes32, to_execution_payload}, Error, }; use ethereum_consensus::{ @@ -20,6 +20,7 @@ use mev_rs::{ }; use reth::{ payload::{EthBuiltPayload, PayloadId}, + rpc::types::engine::ExecutionPayloadEnvelopeV3, tasks::TaskExecutor, }; use serde::Deserialize; @@ -50,6 +51,7 @@ fn prepare_submission( value: payload.fees(), }; let execution_payload = to_execution_payload(payload.block()); + let payload_envelope = ExecutionPayloadEnvelopeV3::from(payload); let signature = sign_builder_message(&message, signing_key, context)?; let submission = match execution_payload.version() { Fork::Bellatrix => { @@ -66,7 +68,12 @@ fn prepare_submission( signature, }) } - Fork::Deneb => unimplemented!(), + Fork::Deneb => SignedBidSubmission::Deneb(block_submission::deneb::SignedBidSubmission { + message, + execution_payload, + blobs_bundle: to_blobs_bundle(payload_envelope.blobs_bundle), + signature, + }), other => unreachable!("fork {other} is not reachable from this type"), }; Ok(submission) diff --git a/mev-build-rs/src/utils/compat.rs b/mev-build-rs/src/utils/compat.rs index f3dfeb5f..7898199e 100644 --- a/mev-build-rs/src/utils/compat.rs +++ b/mev-build-rs/src/utils/compat.rs @@ -1,13 +1,14 @@ use ethereum_consensus::{ capella::mainnet as spec, + deneb::Blob, primitives::{Bytes32, ExecutionAddress}, - ssz::{ - prelude as ssz_rs, - prelude::{ByteList, ByteVector}, - }, + ssz::prelude::{self as ssz_rs, ByteList, ByteVector, List}, +}; +use mev_rs::types::{BlobsBundle, ExecutionPayload}; +use reth::{ + primitives::{Address, Bloom, SealedBlock, B256}, + rpc::types::engine::BlobsBundleV1, }; -use mev_rs::types::ExecutionPayload; -use reth::primitives::{Address, Bloom, SealedBlock, B256}; pub fn to_bytes32(value: B256) -> Bytes32 { Bytes32::try_from(value.as_ref()).unwrap() @@ -61,3 +62,22 @@ pub fn to_execution_payload(value: &SealedBlock) -> ExecutionPayload { }; ExecutionPayload::Capella(payload) } + +pub fn to_blobs_bundle(bundle: BlobsBundleV1) -> BlobsBundle { + let commitments: Vec<_> = bundle + .commitments + .into_iter() + .map(|c| ByteVector::<48>::try_from(c.as_ref()).unwrap()) + .collect(); + let commitments = List::try_from(commitments).unwrap(); + let proofs: Vec<_> = bundle + .proofs + .into_iter() + .map(|p| ByteVector::<48>::try_from(p.as_ref()).unwrap()) + .collect(); + let proofs = List::try_from(proofs).unwrap(); + let blobs: Vec<_> = + bundle.blobs.into_iter().map(|b| Blob::try_from(b.as_ref()).unwrap()).collect(); + let blobs = List::try_from(blobs).unwrap(); + BlobsBundle { commitments, proofs, blobs } +} diff --git a/mev-rs/src/types/auction_contents.rs b/mev-rs/src/types/auction_contents.rs index fc4889f4..3dca94de 100644 --- a/mev-rs/src/types/auction_contents.rs +++ b/mev-rs/src/types/auction_contents.rs @@ -24,9 +24,9 @@ pub mod deneb { #[derive(Clone, Debug, Serializable, HashTreeRoot)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct BlobsBundle { - commitments: List, - proofs: List, - blobs: List, + pub commitments: List, + pub proofs: List, + pub blobs: List, } #[derive(Debug)] diff --git a/mev-rs/src/types/mod.rs b/mev-rs/src/types/mod.rs index 6917db14..d2c7ea35 100644 --- a/mev-rs/src/types/mod.rs +++ b/mev-rs/src/types/mod.rs @@ -4,7 +4,7 @@ pub mod block_submission; pub mod builder_bid; mod proposer_schedule; -pub use auction_contents::AuctionContents; +pub use auction_contents::{deneb::BlobsBundle, AuctionContents}; pub use auction_request::*; pub use block_submission::{BidTrace, SignedBidSubmission}; pub use builder_bid::{BuilderBid, SignedBuilderBid};