diff --git a/crates/rbuilder-operator/src/bidding_service_wrapper/fast_streams/types.rs b/crates/rbuilder-operator/src/bidding_service_wrapper/fast_streams/types.rs index a2a2801f0..bc692e6e6 100644 --- a/crates/rbuilder-operator/src/bidding_service_wrapper/fast_streams/types.rs +++ b/crates/rbuilder-operator/src/bidding_service_wrapper/fast_streams/types.rs @@ -1,6 +1,6 @@ //! Types used to communicate with the bidding service via iceoryx. //! They are mostly mappings of the originals but supporting ZeroCopySend. -use alloy_primitives::U256; +use alloy_primitives::{I256, U256}; use bid_scraper::types::ScrapedRelayBlockBid; use iceoryx2::prelude::ZeroCopySend; use iceoryx2_bb_container::byte_string::FixedSizeByteString; @@ -196,6 +196,7 @@ pub struct SlotBidderSealBidCommandRPC { pub session_id: u64, pub block_id: u64, pub payout_tx_value: [u8; U256_DATA_LENGTH], + pub subsidy: [u8; U256_DATA_LENGTH], pub seen_competition_bid: Option<[u8; U256_DATA_LENGTH]>, /// When this bid is a reaction so some event (eg: new block, new competition bid) we put here /// the creation time of that event so we can measure our reaction time. @@ -213,6 +214,7 @@ impl From for SlotBidderSealBidCommandRPC .0 .trigger_creation_time .map(offset_datetime_to_timestamp_us), + subsidy: value.0.subsidy.to_le_bytes(), } } } @@ -222,6 +224,7 @@ impl From for SlotBidderSealBidCommand { SlotBidderSealBidCommand { block_id: BuiltBlockId(val.block_id), payout_tx_value: U256::from_le_bytes(val.payout_tx_value), + subsidy: I256::from_le_bytes(val.subsidy), seen_competition_bid: val.seen_competition_bid.map(|k| U256::from_le_bytes(k)), trigger_creation_time: val .trigger_creation_time_us diff --git a/crates/rbuilder-operator/src/true_block_value_push/best_true_value_observer.rs b/crates/rbuilder-operator/src/true_block_value_push/best_true_value_observer.rs index a7de3dd53..705f383a4 100644 --- a/crates/rbuilder-operator/src/true_block_value_push/best_true_value_observer.rs +++ b/crates/rbuilder-operator/src/true_block_value_push/best_true_value_observer.rs @@ -83,6 +83,7 @@ impl BidObserver for BestTrueValueObserver { slot_data.slot(), built_block_trace.true_bid_value, built_block_trace.bid_value, + built_block_trace.subsidy, builder_name, slot_data.timestamp().unix_timestamp() as u64, ); diff --git a/crates/rbuilder-operator/src/true_block_value_push/best_true_value_pusher.rs b/crates/rbuilder-operator/src/true_block_value_push/best_true_value_pusher.rs index 87f5c265a..0cc0c03a9 100644 --- a/crates/rbuilder-operator/src/true_block_value_push/best_true_value_pusher.rs +++ b/crates/rbuilder-operator/src/true_block_value_push/best_true_value_pusher.rs @@ -1,9 +1,10 @@ //! This module is responsible for syncing the best true value bid between the local state and redis. -use alloy_primitives::U256; +use alloy_primitives::{I256, U256}; use parking_lot::Mutex; use rbuilder::utils::{ + i256decimal_serde_helper, reconnect::{run_loop_with_reconnect, RunCommand}, u256decimal_serde_helper, }; @@ -27,6 +28,9 @@ pub struct BuiltBlockInfo { /// Bid we made to the relay. #[serde(with = "u256decimal_serde_helper")] pub bid: U256, + #[serde(with = "i256decimal_serde_helper")] + pub subsidy: I256, + pub builder: String, pub slot_end_timestamp: u64, } @@ -37,6 +41,7 @@ impl BuiltBlockInfo { slot_number: u64, best_true_value: U256, bid: U256, + subsidy: I256, builder: String, slot_end_timestamp: u64, ) -> Self { @@ -46,6 +51,7 @@ impl BuiltBlockInfo { slot_number, best_true_value, bid, + subsidy, builder, slot_end_timestamp, } diff --git a/crates/rbuilder/src/building/builders/block_building_helper.rs b/crates/rbuilder/src/building/builders/block_building_helper.rs index 87c268692..66394f1ab 100644 --- a/crates/rbuilder/src/building/builders/block_building_helper.rs +++ b/crates/rbuilder/src/building/builders/block_building_helper.rs @@ -1,4 +1,4 @@ -use alloy_primitives::{utils::format_ether, Address, TxHash, U256}; +use alloy_primitives::{utils::format_ether, Address, TxHash, I256, U256}; use reth_provider::StateProvider; use std::{ cmp::max, @@ -68,10 +68,12 @@ pub trait BlockBuildingHelper: Send + Sync { /// Finalize block for submission. /// if adjust_finalized_block is implemented, finalize_blocks should prepare helper /// for faster adjustments. + /// subsidy is how much of payout_tx_value we consider to be subsidy. fn finalize_block( &mut self, local_ctx: &mut ThreadBlockBuildingContext, payout_tx_value: U256, + subsidy: I256, seen_competition_bid: Option, ) -> Result; @@ -96,6 +98,7 @@ pub trait BlockBuildingHelper: Send + Sync { &mut self, local_ctx: &mut ThreadBlockBuildingContext, payout_tx_value: U256, + subsidy: I256, seen_competition_bid: Option, ) -> Result; } @@ -337,6 +340,7 @@ impl< &mut self, local_ctx: &mut ThreadBlockBuildingContext, payout_tx_value: U256, + subsidy: I256, adjust_finalized_block: bool, finalize_revert_state: &mut FinalizeRevertStateCurrentIteration, ) -> Result<(), BlockBuildingHelperError> { @@ -364,6 +368,7 @@ impl< .unwrap_or_default(); self.built_block_trace.bid_value = max(bid_value, fee_recipient_balance_diff); + self.built_block_trace.subsidy = subsidy; self.built_block_trace.true_bid_value = true_value; self.built_block_trace.mev_blocker_price = self.building_context().mev_blocker_price; Ok(()) @@ -373,6 +378,7 @@ impl< &mut self, local_ctx: &mut ThreadBlockBuildingContext, payout_tx_value: U256, + subsidy: I256, seen_competition_bid: Option, adjust_finalized_block: bool, ) -> Result { @@ -403,6 +409,7 @@ impl< self.finalize_block_execution( local_ctx, payout_tx_value, + subsidy, adjust_finalized_block, &mut finalize_adjustment_state.revert_state, )?; @@ -590,9 +597,16 @@ impl< &mut self, local_ctx: &mut ThreadBlockBuildingContext, payout_tx_value: U256, + subsidy: I256, seen_competition_bid: Option, ) -> Result { - self.finalize_block_impl(local_ctx, payout_tx_value, seen_competition_bid, false) + self.finalize_block_impl( + local_ctx, + payout_tx_value, + subsidy, + seen_competition_bid, + false, + ) } fn built_block_trace(&self) -> &BuiltBlockTrace { @@ -624,8 +638,15 @@ impl< &mut self, local_ctx: &mut ThreadBlockBuildingContext, payout_tx_value: U256, + subsidy: I256, seen_competition_bid: Option, ) -> Result { - self.finalize_block_impl(local_ctx, payout_tx_value, seen_competition_bid, true) + self.finalize_block_impl( + local_ctx, + payout_tx_value, + subsidy, + seen_competition_bid, + true, + ) } } diff --git a/crates/rbuilder/src/building/builders/block_building_helper_stats_logger.rs b/crates/rbuilder/src/building/builders/block_building_helper_stats_logger.rs index 2ab30862f..6ba34084a 100644 --- a/crates/rbuilder/src/building/builders/block_building_helper_stats_logger.rs +++ b/crates/rbuilder/src/building/builders/block_building_helper_stats_logger.rs @@ -4,7 +4,7 @@ use std::{ time::{Duration, Instant}, }; -use alloy_primitives::{utils::format_ether, U256}; +use alloy_primitives::{utils::format_ether, I256, U256}; use crate::{ building::{builders::block_building_helper::BlockBuildingHelper, ThreadBlockBuildingContext}, @@ -208,6 +208,7 @@ impl BlockBuildingHelper for BlockBuildingHelperStatsLogger<'_> { &mut self, _local_ctx: &mut crate::building::ThreadBlockBuildingContext, _payout_tx_value: alloy_primitives::U256, + _subsidy: alloy_primitives::I256, _seen_competition_bid: Option, ) -> Result { panic!("finalize_block not implemented. This is only for testing."); @@ -238,6 +239,7 @@ impl BlockBuildingHelper for BlockBuildingHelperStatsLogger<'_> { &mut self, _local_ctx: &mut ThreadBlockBuildingContext, _payout_tx_value: U256, + _subsidy: I256, _seen_competition_bid: Option, ) -> Result { unimplemented!() diff --git a/crates/rbuilder/src/building/builders/mock_block_building_helper.rs b/crates/rbuilder/src/building/builders/mock_block_building_helper.rs index 59c200f36..ba9e30e6c 100644 --- a/crates/rbuilder/src/building/builders/mock_block_building_helper.rs +++ b/crates/rbuilder/src/building/builders/mock_block_building_helper.rs @@ -7,7 +7,7 @@ use crate::{ provider::RootHasher, roothash::RootHashError, }; -use alloy_primitives::{Address, Bytes, B256, U256}; +use alloy_primitives::{Address, Bytes, B256, I256, U256}; use eth_sparse_mpt::utils::{HashMap, HashSet}; use rbuilder_primitives::{order_statistics::OrderStatistics, SimValue, SimulatedOrder}; use reth_primitives::SealedBlock; @@ -85,11 +85,13 @@ impl BlockBuildingHelper for MockBlockBuildingHelper { &mut self, _local_ctx: &mut ThreadBlockBuildingContext, payout_tx_value: U256, + subsidy: I256, seen_competition_bid: Option, ) -> Result { self.built_block_trace.update_orders_sealed_at(); self.built_block_trace.seen_competition_bid = seen_competition_bid; self.built_block_trace.bid_value = payout_tx_value; + self.built_block_trace.subsidy = subsidy; let block = Block { builder_name: "BlockBuildingHelper".to_string(), trace: self.built_block_trace.clone(), @@ -127,6 +129,7 @@ impl BlockBuildingHelper for MockBlockBuildingHelper { &mut self, _local_ctx: &mut ThreadBlockBuildingContext, _payout_tx_value: U256, + _subsidy: I256, _seen_competition_bid: Option, ) -> Result { unimplemented!() diff --git a/crates/rbuilder/src/building/builders/ordering_builder.rs b/crates/rbuilder/src/building/builders/ordering_builder.rs index f6f9f9770..da5d5bbd0 100644 --- a/crates/rbuilder/src/building/builders/ordering_builder.rs +++ b/crates/rbuilder/src/building/builders/ordering_builder.rs @@ -25,6 +25,7 @@ use crate::{ utils::NonceCache, }; use ahash::{HashMap, HashSet}; +use alloy_primitives::I256; use derivative::Derivative; use rbuilder_primitives::{AccountNonce, OrderId, SimValue, SimulatedOrder}; use reth_provider::StateProvider; @@ -198,7 +199,7 @@ where let payout_tx_value = block_builder.true_block_value()?; let finalize_block_result = - block_builder.finalize_block(&mut local_ctx, payout_tx_value, None)?; + block_builder.finalize_block(&mut local_ctx, payout_tx_value, I256::ZERO, None)?; Ok(finalize_block_result.block) } diff --git a/crates/rbuilder/src/building/builders/parallel_builder/mod.rs b/crates/rbuilder/src/building/builders/parallel_builder/mod.rs index 0ad031e83..9d69646c7 100644 --- a/crates/rbuilder/src/building/builders/parallel_builder/mod.rs +++ b/crates/rbuilder/src/building/builders/parallel_builder/mod.rs @@ -7,6 +7,7 @@ pub mod order_intake_store; pub mod results_aggregator; pub mod simulation_cache; pub mod task; +use alloy_primitives::I256; pub use groups::*; use ahash::HashMap; @@ -377,6 +378,7 @@ where let finalize_block_result = block_building_helper.finalize_block( &mut block_building_result_assembler.local_ctx, payout_tx_value, + I256::ZERO, None, )?; let building_duration = building_start.elapsed(); diff --git a/crates/rbuilder/src/building/built_block_trace.rs b/crates/rbuilder/src/building/built_block_trace.rs index 9dbe433b1..30ff6d994 100644 --- a/crates/rbuilder/src/building/built_block_trace.rs +++ b/crates/rbuilder/src/building/built_block_trace.rs @@ -2,7 +2,7 @@ use crate::building::builders::BuiltBlockId; use super::ExecutionResult; use ahash::{AHasher, HashMap, HashSet}; -use alloy_primitives::{Address, TxHash, U256}; +use alloy_primitives::{Address, TxHash, I256, U256}; use rbuilder_primitives::{ order_statistics::OrderStatistics, Order, OrderId, OrderReplacementKey, SimulatedOrder, }; @@ -18,6 +18,8 @@ pub struct BuiltBlockTrace { pub included_orders: Vec, /// How much we bid (pay to the validator) pub bid_value: U256, + /// Subsidy used in the bid. + pub subsidy: I256, /// coinbase balance delta before the payout tx. pub coinbase_reward: U256, /// True block value (coinbase balance delta) excluding the cost of the payout to validator @@ -96,6 +98,7 @@ impl BuiltBlockTrace { sent_to_sealer: OffsetDateTime::now_utc(), picked_by_sealer_at: OffsetDateTime::now_utc(), build_block_id, + subsidy: I256::ZERO, } } diff --git a/crates/rbuilder/src/live_builder/block_output/bidding_service_interface.rs b/crates/rbuilder/src/live_builder/block_output/bidding_service_interface.rs index b7a2e6a0d..b074d55c2 100644 --- a/crates/rbuilder/src/live_builder/block_output/bidding_service_interface.rs +++ b/crates/rbuilder/src/live_builder/block_output/bidding_service_interface.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use alloy_primitives::{BlockHash, BlockNumber, U256}; +use alloy_primitives::{BlockHash, BlockNumber, I256, U256}; use bid_scraper::{ bid_sender::{BidSender, BidSenderError}, types::ScrapedRelayBlockBid, @@ -104,6 +104,8 @@ impl BuiltBlockDescriptorForSlotBidder { pub struct SlotBidderSealBidCommand { pub block_id: BuiltBlockId, pub payout_tx_value: U256, + /// Subsidy used in the bid. + pub subsidy: I256, pub seen_competition_bid: Option, /// When this bid is a reaction so some event (eg: new block, new competition bid) we put here /// the creation time of that event so we can measure our reaction time. diff --git a/crates/rbuilder/src/live_builder/block_output/true_value_bidding_service.rs b/crates/rbuilder/src/live_builder/block_output/true_value_bidding_service.rs index f14e0e480..ee70a8f56 100644 --- a/crates/rbuilder/src/live_builder/block_output/true_value_bidding_service.rs +++ b/crates/rbuilder/src/live_builder/block_output/true_value_bidding_service.rs @@ -26,6 +26,7 @@ impl SlotBidder for NewTrueBlockValueSlotBidder { payout_tx_value: block_descriptor.true_block_value + self.subsidy, seen_competition_bid: None, trigger_creation_time: Some(time::OffsetDateTime::now_utc()), + subsidy: self.subsidy.try_into().unwrap(), }) } } diff --git a/crates/rbuilder/src/live_builder/block_output/unfinished_block_processing.rs b/crates/rbuilder/src/live_builder/block_output/unfinished_block_processing.rs index b5a26a9bf..dadf90f74 100644 --- a/crates/rbuilder/src/live_builder/block_output/unfinished_block_processing.rs +++ b/crates/rbuilder/src/live_builder/block_output/unfinished_block_processing.rs @@ -11,7 +11,7 @@ /// /// Alternatively if configured (adjust_finalized_blocks = true) to run using old flow `prefinalize_worker` would not do anything with the block /// and `finalize_worker` would do full finalization instead of adjustment of the finalize block. -use alloy_primitives::{utils::format_ether, U256}; +use alloy_primitives::{utils::format_ether, I256, U256}; use derivative::Derivative; use parking_lot::Mutex; use std::sync::Arc; @@ -155,19 +155,20 @@ impl PrefinalizedBlockInner { fn finalize_block( &mut self, value: U256, + subsidy: I256, seen_competition_bid: Option, adjust_finalized_blocks: bool, ) -> Result, BlockBuildingHelperError> { if let Some(local_ctx) = self.local_ctx.as_mut() { if adjust_finalized_blocks { self.block_building_helper - .adjust_finalized_block(local_ctx, value, seen_competition_bid) + .adjust_finalized_block(local_ctx, value, subsidy, seen_competition_bid) .map(Some) } else { // we clone here because finalizing block multiple times is not supported self.block_building_helper .box_clone() - .finalize_block(local_ctx, value, seen_competition_bid) + .finalize_block(local_ctx, value, subsidy, seen_competition_bid) .map(Some) } } else { @@ -207,6 +208,7 @@ impl PrefinalizedBlock { struct FinalizeCommand { prefinalized_block: PrefinalizedBlock, value: U256, + subsidy: I256, seen_competition_bid: Option, /// Bid received from the bidder (UnfinishedBuiltBlocksInput::seal_command) bid_received_at: OffsetDateTime, @@ -326,6 +328,7 @@ impl UnfinishedBuiltBlocksInput { seen_competition_bid: bid.seen_competition_bid, bid_received_at, sent_to_sealer, + subsidy: bid.subsidy, }; self.last_finalize_command.set(finalize_command); } else { @@ -382,7 +385,8 @@ impl UnfinishedBuiltBlocksInput { continue; } }; - match block_building_helper.finalize_block(&mut local_ctx, value, None) { + match block_building_helper.finalize_block(&mut local_ctx, value, I256::ZERO, None) + { Ok(_) => { trace!("Prefinalized block"); } @@ -437,6 +441,7 @@ impl UnfinishedBuiltBlocksInput { let mut result = match command.finalize_block( finalize_command.value, + finalize_command.subsidy, finalize_command.seen_competition_bid, self.adjust_finalized_blocks, ) { diff --git a/crates/rbuilder/src/utils/mod.rs b/crates/rbuilder/src/utils/mod.rs index 1d9b844b3..c9239b201 100644 --- a/crates/rbuilder/src/utils/mod.rs +++ b/crates/rbuilder/src/utils/mod.rs @@ -69,6 +69,31 @@ pub mod u256decimal_serde_helper { } } +/// de/serializes U256 as decimal value (U256 serde default is hexa). Needed to interact with some JSONs (eg:ProposerPayloadDelivered in relay provider API) +pub mod i256decimal_serde_helper { + use std::str::FromStr; + + use alloy_primitives::I256; + use serde::{Deserialize, Deserializer, Serializer}; + + pub fn serialize(value: &I256, serializer: S) -> Result + where + S: Serializer, + { + //fmt::Display for I256 uses decimal + serializer.serialize_str(&value.to_string()) + } + + pub fn deserialize<'de, D>(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let s = String::deserialize(deserializer)?; + //from_str is robust, can take decimal or other prefixed (eg:"0x" hexa) formats. + I256::from_str(&s).map_err(serde::de::Error::custom) + } +} + pub fn http_provider(url: reqwest::Url) -> RootProvider { RootProvider::new_http(url) }