Skip to content
8 changes: 8 additions & 0 deletions crates/op-rbuilder/src/args/op.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,14 @@ pub struct FlashblocksArgs {
env = "FLASHBLOCK_LEEWAY_TIME"
)]
pub flashblocks_leeway_time: u64,

/// Should we calculate state root for each flashblock
#[arg(
long = "flashblocks.calculate-state-root",
default_value = "true",
env = "FLASHBLOCKS_CALCULATE_STATE_ROOT"
)]
pub flashblocks_calculate_state_root: bool,
}

impl Default for FlashblocksArgs {
Expand Down
7 changes: 7 additions & 0 deletions crates/op-rbuilder/src/builders/flashblocks/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ pub struct FlashblocksConfig {

/// Disables dynamic flashblocks number adjustment based on FCU arrival time
pub fixed: bool,

/// Should we calculate state root for each flashblock
pub calculate_state_root: bool,
}

impl Default for FlashblocksConfig {
Expand All @@ -37,6 +40,7 @@ impl Default for FlashblocksConfig {
interval: Duration::from_millis(250),
leeway_time: Duration::from_millis(50),
fixed: false,
calculate_state_root: true,
}
}
}
Expand All @@ -56,11 +60,14 @@ impl TryFrom<OpRbuilderArgs> for FlashblocksConfig {

let fixed = args.flashblocks.flashblocks_fixed;

let calculate_state_root = args.flashblocks.flashblocks_calculate_state_root;

Ok(Self {
ws_addr,
interval,
leeway_time,
fixed,
calculate_state_root,
})
}
}
Expand Down
88 changes: 56 additions & 32 deletions crates/op-rbuilder/src/builders/flashblocks/payload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ use reth_provider::{
use reth_revm::{
database::StateProviderDatabase, db::states::bundle_state::BundleRetention, State,
};
use reth_trie::{updates::TrieUpdates, HashedPostState};
use revm::Database;
use rollup_boost::{
ExecutionPayloadBaseV1, ExecutionPayloadFlashblockDeltaV1, FlashblocksPayloadV1,
Expand All @@ -46,7 +47,7 @@ use std::{
atomic::{AtomicU64, Ordering},
Arc,
},
time::Instant,
time::{Instant, SystemTime, UNIX_EPOCH},
};
use tokio::sync::{
mpsc,
Expand Down Expand Up @@ -192,6 +193,10 @@ where
best_payload: BlockCell<OpBuiltPayload>,
) -> Result<(), PayloadBuilderError> {
let block_build_start_time = Instant::now();
let current_timestamp = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs();
let BuildArguments {
mut cached_reads,
config,
Expand All @@ -214,6 +219,12 @@ where

let chain_spec = self.client.chain_spec();
let timestamp = config.attributes.timestamp();
let is_doing_historical_sync = timestamp < current_timestamp;
let calculate_state_root = if is_doing_historical_sync {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need to build blocks and calculate the state root during historical sync?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

answered here
#241 (comment)

true
} else {
self.config.specific.calculate_state_root
};
let block_env_attributes = OpNextBlockEnvAttributes {
timestamp,
suggested_fee_recipient: config.attributes.suggested_fee_recipient(),
Expand Down Expand Up @@ -288,16 +299,18 @@ where
ctx.add_builder_tx(&mut info, &mut state, builder_tx_gas, message.clone());
}

let (payload, fb_payload) = build_block(&mut state, &ctx, &mut info)?;
let (payload, fb_payload) = build_block(&mut state, &ctx, &mut info, calculate_state_root)?;

best_payload.set(payload.clone());
let flashblock_byte_size = self
.ws_pub
.publish(&fb_payload)
.map_err(PayloadBuilderError::other)?;
ctx.metrics
.flashblock_byte_size_histogram
.record(flashblock_byte_size as f64);
if !is_doing_historical_sync {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

solves the issue that it'd stream out flashblocks while historical syncing

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How exactly does it happen? As i understand if we are doing historical syncing we will answer SYNCING to FCU with attributes and don't start block building job

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC that's when you are doing EL sync, for us we are still doing CL sync so this happens somehow

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does CL sync need to trigger a block building job? Can't you short circuit the block building much earlier during CL sync

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure why it triggers but payload builder does get used during CL historical sync
What do you mean by short circuit the block building?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only FCU w/ attr will initiate job creating
Are you replaying ALL cl historical calls (including FCU w/ attr and getPayload's)?
I think you should filter them out when you perform CL sync

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like those FCUs are coming from the CL, which aren't filtered out by rollup-boost.

Instead of doing the timestamp check i'm now using no_tx_pool check instead

let flashblock_byte_size = self
.ws_pub
.publish(&fb_payload)
.map_err(PayloadBuilderError::other)?;
ctx.metrics
.flashblock_byte_size_histogram
.record(flashblock_byte_size as f64);
}

info!(
target: "payload_builder",
Expand Down Expand Up @@ -484,7 +497,8 @@ where
};

let total_block_built_duration = Instant::now();
let build_result = build_block(&mut state, &ctx, &mut info);
let build_result =
build_block(&mut state, &ctx, &mut info, calculate_state_root);
let total_block_built_duration = total_block_built_duration.elapsed();
ctx.metrics
.total_block_built_duration
Expand Down Expand Up @@ -770,6 +784,7 @@ fn build_block<DB, P, ExtraCtx>(
state: &mut State<DB>,
ctx: &OpPayloadBuilderCtx<ExtraCtx>,
info: &mut ExecutionInfo<ExtraExecutionInfo>,
calculate_state_root: bool,
) -> Result<(OpBuiltPayload, FlashblocksPayloadV1), PayloadBuilderError>
where
DB: Database<Error = ProviderError> + AsRef<P>,
Expand Down Expand Up @@ -814,28 +829,37 @@ where
// TODO: maybe recreate state with bundle in here
// // calculate the state root
let state_root_start_time = Instant::now();
let state_provider = state.database.as_ref();
let hashed_state = state_provider.hashed_post_state(execution_outcome.state());
let (state_root, trie_output) = {
state
.database
.as_ref()
.state_root_with_updates(hashed_state.clone())
.inspect_err(|err| {
warn!(target: "payload_builder",
parent_header=%ctx.parent().hash(),
%err,
"failed to calculate state root for payload"
);
})?
};
let state_root_calculation_time = state_root_start_time.elapsed();
ctx.metrics
.state_root_calculation_duration
.record(state_root_calculation_time);
ctx.metrics
.state_root_calculation_gauge
.set(state_root_calculation_time);
let mut state_root = B256::ZERO;
let mut trie_output = TrieUpdates::default();
let mut hashed_state = HashedPostState::default();

if calculate_state_root {
let state_provider = state.database.as_ref();
let _hashed_state = state_provider.hashed_post_state(execution_outcome.state());
let (_state_root, _trie_output) = {
state
.database
.as_ref()
.state_root_with_updates(hashed_state.clone())
.inspect_err(|err| {
warn!(target: "payload_builder",
parent_header=%ctx.parent().hash(),
%err,
"failed to calculate state root for payload"
);
})?
};
let state_root_calculation_time = state_root_start_time.elapsed();
ctx.metrics
.state_root_calculation_duration
.record(state_root_calculation_time);
ctx.metrics
.state_root_calculation_gauge
.set(state_root_calculation_time);
state_root = _state_root;
trie_output = _trie_output;
hashed_state = _hashed_state;
}

let mut requests_hash = None;
let withdrawals_root = if ctx
Expand Down
8 changes: 8 additions & 0 deletions crates/op-rbuilder/src/tests/flashblocks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use crate::{
flashblocks_block_time: 200,
flashblocks_leeway_time: 100,
flashblocks_fixed: false,
flashblocks_calculate_state_root: true,
},
..Default::default()
})]
Expand Down Expand Up @@ -89,6 +90,7 @@ async fn smoke_dynamic_base(rbuilder: LocalInstance) -> eyre::Result<()> {
flashblocks_block_time: 200,
flashblocks_leeway_time: 100,
flashblocks_fixed: false,
flashblocks_calculate_state_root: true,
},
..Default::default()
})]
Expand Down Expand Up @@ -157,6 +159,7 @@ async fn smoke_dynamic_unichain(rbuilder: LocalInstance) -> eyre::Result<()> {
flashblocks_block_time: 200,
flashblocks_leeway_time: 50,
flashblocks_fixed: true,
flashblocks_calculate_state_root: true,
},
..Default::default()
})]
Expand Down Expand Up @@ -225,6 +228,7 @@ async fn smoke_classic_unichain(rbuilder: LocalInstance) -> eyre::Result<()> {
flashblocks_block_time: 200,
flashblocks_leeway_time: 50,
flashblocks_fixed: true,
flashblocks_calculate_state_root: true,
},
..Default::default()
})]
Expand Down Expand Up @@ -293,6 +297,7 @@ async fn smoke_classic_base(rbuilder: LocalInstance) -> eyre::Result<()> {
flashblocks_block_time: 200,
flashblocks_leeway_time: 100,
flashblocks_fixed: false,
flashblocks_calculate_state_root: true,
},
..Default::default()
})]
Expand Down Expand Up @@ -363,6 +368,7 @@ async fn unichain_dynamic_with_lag(rbuilder: LocalInstance) -> eyre::Result<()>
flashblocks_block_time: 200,
flashblocks_leeway_time: 0,
flashblocks_fixed: false,
flashblocks_calculate_state_root: true,
},
..Default::default()
})]
Expand Down Expand Up @@ -430,6 +436,7 @@ async fn dynamic_with_full_block_lag(rbuilder: LocalInstance) -> eyre::Result<()
flashblocks_block_time: 200,
flashblocks_leeway_time: 100,
flashblocks_fixed: false,
flashblocks_calculate_state_root: true,
},
..Default::default()
})]
Expand Down Expand Up @@ -525,6 +532,7 @@ async fn test_flashblock_min_filtering(rbuilder: LocalInstance) -> eyre::Result<
flashblocks_block_time: 200,
flashblocks_leeway_time: 100,
flashblocks_fixed: false,
flashblocks_calculate_state_root: true,
},
..Default::default()
})]
Expand Down
Loading