Skip to content

Commit 8b3ac6a

Browse files
committed
feat: refresh fb candidate and only build block when better
1 parent b43522f commit 8b3ac6a

File tree

1 file changed

+33
-25
lines changed
  • crates/op-rbuilder/src/builders/flashblocks

1 file changed

+33
-25
lines changed

crates/op-rbuilder/src/builders/flashblocks/payload.rs

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -810,11 +810,18 @@ where
810810
}
811811
}
812812

813-
fn build_candidate<
813+
/// Takes the current best flashblock candidate, execute new transaction and build a new candidate only if it's better
814+
#[expect(clippy::too_many_arguments)]
815+
fn refresh_best_flashblock_candidate<
814816
DB: Database<Error = ProviderError> + std::fmt::Debug + AsRef<P>,
815817
P: StateRootProvider + HashedPostStateProvider + StorageRootProvider,
816818
>(
817819
&self,
820+
best: Option<(
821+
OpBuiltPayload,
822+
FlashblocksPayloadV1,
823+
ExecutionInfo<FlashblocksExecutionInfo>,
824+
)>,
818825
ctx: &OpPayloadBuilderCtx<FlashblocksExtraCtx>,
819826
state: &mut State<DB>,
820827
state_provider: impl reth::providers::StateProvider + Clone,
@@ -859,20 +866,32 @@ where
859866
error!(target: "payload_builder", "Error simulating builder txs: {}", e);
860867
};
861868

862-
// build block
863-
let build_result = build_block(
869+
// Check if we can build a better block by comparing execution results
870+
let is_better_candidate = |prev: &ExecutionInfo<_>, new: &ExecutionInfo<_>| {
871+
new.cumulative_gas_used > prev.cumulative_gas_used
872+
};
873+
if best
874+
.as_ref()
875+
.is_some_and(|(_, _, prev)| !is_better_candidate(prev, &batch_info))
876+
{
877+
// Not better, nothing to refresh so we can return early
878+
return Ok(best.expect("safe: best matched Some"));
879+
}
880+
881+
// build block and return new best
882+
build_block(
864883
state, // todo
865884
ctx,
866885
&mut batch_info,
867886
ctx.extra_ctx.calculate_state_root || ctx.attributes().no_tx_pool,
868-
);
869-
build_result
870-
.map(|(payload, mut fb)| {
871-
fb.index = ctx.flashblock_index();
872-
fb.base = None;
873-
(payload, fb, batch_info)
874-
})
875-
.wrap_err("failed to build payload")
887+
)
888+
.map(|(payload, mut fb)| {
889+
fb.index = ctx.flashblock_index();
890+
fb.base = None;
891+
892+
(payload, fb, batch_info)
893+
})
894+
.wrap_err("failed to build payload")
876895
}
877896

878897
#[expect(clippy::too_many_arguments)]
@@ -933,26 +952,15 @@ where
933952

934953
// Build one candidate (blocking here)
935954
// todo: would be best to build async and select on candidate_build/block_cancel/fb_cancel
936-
match self.build_candidate(
955+
best = Some(self.refresh_best_flashblock_candidate(
956+
best,
937957
&*ctx,
938958
state,
939959
&state_provider,
940960
best_txs,
941961
target_gas_for_batch,
942962
target_da_for_batch,
943-
) {
944-
Ok(candidate) => {
945-
if best
946-
.as_ref()
947-
.is_none_or(|b| candidate.1.diff.gas_used > b.1.diff.gas_used)
948-
{
949-
best = Some(candidate);
950-
}
951-
}
952-
Err(_) => {
953-
ctx.metrics.invalid_blocks_count.increment(1);
954-
}
955-
}
963+
)?);
956964
}
957965

958966
// 3. --- Cancellation token received, send best ---

0 commit comments

Comments
 (0)