From b3e611e3b6f87d85e030b2fa8ac140a61eaf6943 Mon Sep 17 00:00:00 2001 From: Francis Li Date: Wed, 19 Nov 2025 21:22:16 -0800 Subject: [PATCH] Update to use op-alloy flashblock types --- .../src/builders/flashblocks/payload.rs | 60 +++++++++++-------- .../builders/flashblocks/payload_handler.rs | 4 +- .../src/builders/flashblocks/wspub.rs | 6 +- 3 files changed, 41 insertions(+), 29 deletions(-) diff --git a/crates/op-rbuilder/src/builders/flashblocks/payload.rs b/crates/op-rbuilder/src/builders/flashblocks/payload.rs index cb91116e5..339a8e3f8 100644 --- a/crates/op-rbuilder/src/builders/flashblocks/payload.rs +++ b/crates/op-rbuilder/src/builders/flashblocks/payload.rs @@ -16,20 +16,24 @@ use alloy_consensus::{ BlockBody, EMPTY_OMMER_ROOT_HASH, Header, constants::EMPTY_WITHDRAWALS, proofs, }; use alloy_eips::{Encodable2718, eip7685::EMPTY_REQUESTS_HASH, merge::BEACON_NONCE}; -use alloy_primitives::{Address, B256, U256, map::foldhash::HashMap}; +use alloy_primitives::{Address, B256, U256}; use core::time::Duration; use either::Either; use eyre::WrapErr as _; +use op_alloy_rpc_types_engine::{ + OpFlashblockPayload, OpFlashblockPayloadBase, OpFlashblockPayloadDelta, + OpFlashblockPayloadMetadata, +}; use reth::payload::PayloadBuilderAttributes; use reth_basic_payload_builder::BuildOutcome; use reth_chainspec::EthChainSpec; use reth_evm::{ConfigureEvm, execute::BlockBuilder}; -use reth_node_api::{Block, NodePrimitives, PayloadBuilderError}; +use reth_node_api::{Block, PayloadBuilderError}; use reth_optimism_consensus::{calculate_receipt_root_no_memo_optimism, isthmus}; use reth_optimism_evm::{OpEvmConfig, OpNextBlockEnvAttributes}; use reth_optimism_forks::OpHardforks; use reth_optimism_node::{OpBuiltPayload, OpPayloadBuilderAttributes}; -use reth_optimism_primitives::{OpPrimitives, OpReceipt, OpTransactionSigned}; +use reth_optimism_primitives::{OpReceipt, OpTransactionSigned}; use reth_payload_primitives::BuiltPayloadExecutedBlock; use reth_payload_util::BestPayloadTransactions; use reth_primitives_traits::RecoveredBlock; @@ -43,11 +47,8 @@ use reth_revm::{ use reth_transaction_pool::TransactionPool; use reth_trie::{HashedPostState, updates::TrieUpdates}; use revm::Database; -use rollup_boost::{ - ExecutionPayloadBaseV1, ExecutionPayloadFlashblockDeltaV1, FlashblocksPayloadV1, -}; -use serde::{Deserialize, Serialize}; use std::{ + collections::BTreeMap, ops::{Div, Rem}, sync::Arc, time::Instant, @@ -56,6 +57,24 @@ use tokio::sync::mpsc; use tokio_util::sync::CancellationToken; use tracing::{debug, error, info, metadata::Level, span, warn}; +/// Converts a reth OpReceipt to an op-alloy OpReceipt +/// TODO: remove this once reth updates to use the op-alloy defined type as well. +fn convert_receipt(receipt: &OpReceipt) -> op_alloy_consensus::OpReceipt { + match receipt { + OpReceipt::Legacy(r) => op_alloy_consensus::OpReceipt::Legacy(r.clone()), + OpReceipt::Eip2930(r) => op_alloy_consensus::OpReceipt::Eip2930(r.clone()), + OpReceipt::Eip1559(r) => op_alloy_consensus::OpReceipt::Eip1559(r.clone()), + OpReceipt::Eip7702(r) => op_alloy_consensus::OpReceipt::Eip7702(r.clone()), + OpReceipt::Deposit(r) => { + op_alloy_consensus::OpReceipt::Deposit(op_alloy_consensus::OpDepositReceipt { + inner: r.inner.clone(), + deposit_nonce: r.deposit_nonce, + deposit_receipt_version: r.deposit_receipt_version, + }) + } + } +} + type NextBestFlashblocksTxs = BestFlashblocksTxs< ::Transaction, Box< @@ -916,13 +935,6 @@ where } } -#[derive(Debug, Serialize, Deserialize)] -struct FlashblocksMetadata { - receipts: HashMap::Receipt>, - new_account_balances: HashMap, - block_number: u64, -} - fn execute_pre_steps( state: &mut State, ctx: &OpPayloadBuilderCtx, @@ -948,7 +960,7 @@ pub(super) fn build_block( ctx: &OpPayloadBuilderCtx, info: &mut ExecutionInfo, calculate_state_root: bool, -) -> Result<(OpBuiltPayload, FlashblocksPayloadV1), PayloadBuilderError> +) -> Result<(OpBuiltPayload, OpFlashblockPayload), PayloadBuilderError> where DB: Database + AsRef

, P: StateRootProvider + HashedPostStateProvider + StorageRootProvider, @@ -1115,16 +1127,16 @@ where let receipts_with_hash = new_transactions .iter() .zip(new_receipts.iter()) - .map(|(tx, receipt)| (tx.tx_hash(), receipt.clone())) - .collect::>(); + .map(|(tx, receipt)| (tx.tx_hash(), convert_receipt(receipt))) + .collect::>(); let new_account_balances = state .bundle_state .state .iter() .filter_map(|(address, account)| account.info.as_ref().map(|info| (*address, info.balance))) - .collect::>(); + .collect::>(); - let metadata: FlashblocksMetadata = FlashblocksMetadata { + let metadata = OpFlashblockPayloadMetadata { receipts: receipts_with_hash, new_account_balances, block_number: ctx.parent().number + 1, @@ -1133,10 +1145,10 @@ where let (_, blob_gas_used) = ctx.blob_fields(info); // Prepare the flashblocks message - let fb_payload = FlashblocksPayloadV1 { + let fb_payload = OpFlashblockPayload { payload_id: ctx.payload_id(), index: 0, - base: Some(ExecutionPayloadBaseV1 { + base: Some(OpFlashblockPayloadBase { parent_beacon_block_root: ctx .attributes() .payload_attributes @@ -1149,9 +1161,9 @@ where gas_limit: ctx.block_gas_limit(), timestamp: ctx.attributes().payload_attributes.timestamp, extra_data: ctx.extra_data()?, - base_fee_per_gas: ctx.base_fee().try_into().unwrap(), + base_fee_per_gas: U256::from(ctx.base_fee()), }), - diff: ExecutionPayloadFlashblockDeltaV1 { + diff: OpFlashblockPayloadDelta { state_root, receipts_root, logs_bloom, @@ -1162,7 +1174,7 @@ where withdrawals_root: withdrawals_root.unwrap_or_default(), blob_gas_used, }, - metadata: serde_json::to_value(&metadata).unwrap_or_default(), + metadata, }; // We clean bundle and place initial state transaction back diff --git a/crates/op-rbuilder/src/builders/flashblocks/payload_handler.rs b/crates/op-rbuilder/src/builders/flashblocks/payload_handler.rs index 96b6f683a..8613abc86 100644 --- a/crates/op-rbuilder/src/builders/flashblocks/payload_handler.rs +++ b/crates/op-rbuilder/src/builders/flashblocks/payload_handler.rs @@ -9,6 +9,7 @@ use alloy_evm::eth::receipt_builder::ReceiptBuilderCtx; use alloy_primitives::B64; use eyre::{WrapErr as _, bail}; use op_alloy_consensus::OpTxEnvelope; +use op_alloy_rpc_types_engine::OpFlashblockPayload; use reth::revm::{State, database::StateProviderDatabase}; use reth_basic_payload_builder::PayloadConfig; use reth_evm::FromRecoveredTx; @@ -19,7 +20,6 @@ use reth_optimism_node::{OpEngineTypes, OpPayloadBuilderAttributes}; use reth_optimism_payload_builder::OpBuiltPayload; use reth_optimism_primitives::{OpReceipt, OpTransactionSigned}; use reth_payload_builder::EthPayloadBuilderAttributes; -use rollup_boost::FlashblocksPayloadV1; use std::sync::Arc; use tokio::sync::mpsc; use tracing::warn; @@ -135,7 +135,7 @@ fn execute_flashblock( ctx: OpPayloadSyncerCtx, client: Client, cancel: tokio_util::sync::CancellationToken, -) -> eyre::Result<(OpBuiltPayload, FlashblocksPayloadV1)> +) -> eyre::Result<(OpBuiltPayload, OpFlashblockPayload)> where Client: ClientBounds, { diff --git a/crates/op-rbuilder/src/builders/flashblocks/wspub.rs b/crates/op-rbuilder/src/builders/flashblocks/wspub.rs index e2f003dc1..acdbf0c28 100644 --- a/crates/op-rbuilder/src/builders/flashblocks/wspub.rs +++ b/crates/op-rbuilder/src/builders/flashblocks/wspub.rs @@ -5,7 +5,7 @@ use core::{ }; use futures::SinkExt; use futures_util::StreamExt; -use rollup_boost::FlashblocksPayloadV1; +use op_alloy_rpc_types_engine::OpFlashblockPayload; use std::{io, net::TcpListener, sync::Arc}; use tokio::{ net::TcpStream, @@ -25,7 +25,7 @@ use crate::metrics::OpRBuilderMetrics; /// A WebSockets publisher that accepts connections from client websockets and broadcasts to them /// updates about new flashblocks. It maintains a count of sent messages and active subscriptions. /// -/// This is modelled as a `futures::Sink` that can be used to send `FlashblocksPayloadV1` messages. +/// This is modelled as a `futures::Sink` that can be used to send `OpFlashblockPayload` messages. pub(super) struct WebSocketPublisher { sent: Arc, subs: Arc, @@ -59,7 +59,7 @@ impl WebSocketPublisher { }) } - pub(super) fn publish(&self, payload: &FlashblocksPayloadV1) -> io::Result { + pub(super) fn publish(&self, payload: &OpFlashblockPayload) -> io::Result { // Serialize the payload to a UTF-8 string // serialize only once, then just copy around only a pointer // to the serialized data for each subscription.