From beb8fac91ba49c8c71654faae3a8ff0f5c7c1db3 Mon Sep 17 00:00:00 2001 From: Varun Doshi Date: Sat, 5 Jul 2025 09:58:10 +0530 Subject: [PATCH] feat: add v5 flashbots relay block validation api for Fusaka (#17179) Co-authored-by: Matthias Seitz --- crates/rpc/rpc-api/src/validation.rs | 8 ++++ crates/rpc/rpc/Cargo.toml | 2 +- crates/rpc/rpc/src/validation.rs | 70 +++++++++++++++++++++++++++- 3 files changed, 77 insertions(+), 3 deletions(-) diff --git a/crates/rpc/rpc-api/src/validation.rs b/crates/rpc/rpc-api/src/validation.rs index 5e4f2e2614..9ff47b5eaf 100644 --- a/crates/rpc/rpc-api/src/validation.rs +++ b/crates/rpc/rpc-api/src/validation.rs @@ -3,6 +3,7 @@ use alloy_rpc_types_beacon::relay::{ BuilderBlockValidationRequest, BuilderBlockValidationRequestV2, BuilderBlockValidationRequestV3, BuilderBlockValidationRequestV4, + BuilderBlockValidationRequestV5, }; use jsonrpsee::proc_macros::rpc; @@ -37,4 +38,11 @@ pub trait BlockSubmissionValidationApi { &self, request: BuilderBlockValidationRequestV4, ) -> jsonrpsee::core::RpcResult<()>; + + /// A Request to validate a block submission. + #[method(name = "validateBuilderSubmissionV5")] + async fn validate_builder_submission_v5( + &self, + request: BuilderBlockValidationRequestV5, + ) -> jsonrpsee::core::RpcResult<()>; } diff --git a/crates/rpc/rpc/Cargo.toml b/crates/rpc/rpc/Cargo.toml index 2f41caa548..389502a2c7 100644 --- a/crates/rpc/rpc/Cargo.toml +++ b/crates/rpc/rpc/Cargo.toml @@ -60,7 +60,7 @@ alloy-rpc-types-trace.workspace = true alloy-rpc-types-mev.workspace = true alloy-rpc-types-txpool.workspace = true alloy-rpc-types-admin.workspace = true -alloy-rpc-types-engine.workspace = true +alloy-rpc-types-engine = { workspace = true, features = ["kzg"] } alloy-serde.workspace = true revm = { workspace = true, features = ["optional_block_gas_limit", "optional_eip3607", "optional_no_base_fee"] } revm-primitives = { workspace = true, features = ["serde"] } diff --git a/crates/rpc/rpc/src/validation.rs b/crates/rpc/rpc/src/validation.rs index e2d5a553d5..6ec2a1b720 100644 --- a/crates/rpc/rpc/src/validation.rs +++ b/crates/rpc/rpc/src/validation.rs @@ -5,10 +5,11 @@ use alloy_eips::{eip4844::kzg_to_versioned_hash, eip7685::RequestsOrHash}; use alloy_rpc_types_beacon::relay::{ BidTrace, BuilderBlockValidationRequest, BuilderBlockValidationRequestV2, BuilderBlockValidationRequestV3, BuilderBlockValidationRequestV4, + BuilderBlockValidationRequestV5, }; use alloy_rpc_types_engine::{ - BlobsBundleV1, CancunPayloadFields, ExecutionData, ExecutionPayload, ExecutionPayloadSidecar, - PraguePayloadFields, + BlobsBundleV1, BlobsBundleV2, CancunPayloadFields, ExecutionData, ExecutionPayload, + ExecutionPayloadSidecar, PraguePayloadFields, }; use async_trait::async_trait; use core::fmt; @@ -365,6 +366,24 @@ where Ok(versioned_hashes) } + /// Validates the given [`BlobsBundleV1`] and returns versioned hashes for blobs. + pub fn validate_blobs_bundle_v2( + &self, + blobs_bundle: BlobsBundleV2, + ) -> Result, ValidationApiError> { + let versioned_hashes = blobs_bundle + .commitments + .iter() + .map(|c| kzg_to_versioned_hash(c.as_slice())) + .collect::>(); + + blobs_bundle + .try_into_sidecar() + .map_err(|_| ValidationApiError::InvalidBlobsBundle)? + .validate(&versioned_hashes, EnvKzgSettings::default().get())?; + + Ok(versioned_hashes) + } /// Core logic for validating the builder submission v3 async fn validate_builder_submission_v3( @@ -414,6 +433,35 @@ where ) .await } + + /// Core logic for validating the builder submission v5 + async fn validate_builder_submission_v5( + &self, + request: BuilderBlockValidationRequestV5, + ) -> Result<(), ValidationApiError> { + let block = self.payload_validator.ensure_well_formed_payload(ExecutionData { + payload: ExecutionPayload::V3(request.request.execution_payload), + sidecar: ExecutionPayloadSidecar::v4( + CancunPayloadFields { + parent_beacon_block_root: request.parent_beacon_block_root, + versioned_hashes: self + .validate_blobs_bundle_v2(request.request.blobs_bundle)?, + }, + PraguePayloadFields { + requests: RequestsOrHash::Requests( + request.request.execution_requests.to_requests(), + ), + }, + ), + })?; + + self.validate_message_against_block( + block, + request.request.message, + request.registered_gas_limit, + ) + .await + } } #[async_trait] @@ -477,6 +525,24 @@ where rx.await.map_err(|_| internal_rpc_err("Internal blocking task error"))? } + + /// Validates a block submitted to the relay + async fn validate_builder_submission_v5( + &self, + request: BuilderBlockValidationRequestV5, + ) -> RpcResult<()> { + let this = self.clone(); + let (tx, rx) = oneshot::channel(); + + self.task_spawner.spawn_blocking(Box::pin(async move { + let result = Self::validate_builder_submission_v5(&this, request) + .await + .map_err(ErrorObject::from); + let _ = tx.send(result); + })); + + rx.await.map_err(|_| internal_rpc_err("Internal blocking task error"))? + } } pub struct ValidationApiInner {