@@ -37,7 +37,8 @@ use strata_ol_state_types::{
3737use strata_ol_state_types_v1:: { IStateBatchApplicable , OLStateV1 , WriteBatch } ;
3838use strata_ol_stf:: {
3939 BlockInfo , EpochDaReplayError , EpochInfo , EpochSpecSelectionError , OLSpecId , apply_da_epoch,
40- select_next_epoch_spec, verify_block,
40+ select_next_epoch_spec, sequencer:: verify_block_structure, verify_block,
41+ verify_header_continuity,
4142} ;
4243use strata_primitives:: epoch:: EpochCommitment ;
4344use strata_service:: ServiceState ;
@@ -48,6 +49,7 @@ use crate::{
4849 ChainWorkerContextImpl ,
4950 errors:: { WorkerError , WorkerResult } ,
5051 output:: OLBlockExecutionOutput ,
52+ provenance:: validate_manifests,
5153 traits:: ChainWorkerContext ,
5254} ;
5355
@@ -331,10 +333,44 @@ fn fetch_block_with_parent(
331333 Ok ( ( block, parent_header, parent_commitment) )
332334}
333335
336+ /// Validates all block inputs without executing or persisting state.
337+ fn validate_block_inputs (
338+ spec : OLSpecId ,
339+ ctx : & impl ChainWorkerContext ,
340+ block : & OLBlockV1 ,
341+ parent_header : Option < & OLBlockHeaderV1 > ,
342+ parent_state : & impl IStateAccessor ,
343+ ) -> WorkerResult < ( ) > {
344+ verify_header_continuity ( spec, block. header ( ) , parent_header) ?;
345+ verify_block_structure ( spec, block. header ( ) , block. body ( ) ) ?;
346+ if let Some ( container) = block. body ( ) . manifests ( ) {
347+ validate_manifests (
348+ ctx,
349+ spec,
350+ parent_state. last_l1_height ( ) ,
351+ container. manifests ( ) ,
352+ ) ?;
353+ }
354+ Ok ( ( ) )
355+ }
356+
357+ /// Loads the parent state used by input validation and STF execution, keeping its
358+ /// spec versions.
359+ fn fetch_parent_state (
360+ ctx : & impl ChainWorkerContext ,
361+ parent_commitment : OLBlockCommitment ,
362+ ) -> WorkerResult < MemoryStateBaseLayer < OLStateV1 > > {
363+ let parent_state = ctx
364+ . fetch_ol_state ( parent_commitment) ?
365+ . ok_or ( WorkerError :: MissingPreState ( parent_commitment) ) ?;
366+ Ok ( MemoryStateBaseLayer :: from_container ( parent_state) )
367+ }
368+
334369/// Executes the STF on a block and returns the execution output.
335370///
336371/// This fetches parent state, builds the state stack, runs verification,
337372/// and extracts the resulting write batch and indexer writes.
373+ /// Callers classify failures; pending canonical manifests are expected during L1 catch-up.
338374#[ instrument(
339375 skip_all,
340376 fields(
@@ -344,7 +380,6 @@ fn fetch_block_with_parent(
344380 is_terminal = block. header( ) . is_terminal( ) ,
345381 %parent_commitment,
346382 ) ,
347- err,
348383) ]
349384fn execute_stf (
350385 ctx : & impl ChainWorkerContext ,
@@ -354,12 +389,8 @@ fn execute_stf(
354389 parent_header : Option < & OLBlockHeaderV1 > ,
355390 parent_commitment : OLBlockCommitment ,
356391) -> WorkerResult < ( OLBlockExecutionOutput , OLStateContainer ) > {
357- // Fetch parent state and build its state accessor, keeping its spec
358- // versions.
359- let parent_state_raw = ctx
360- . fetch_ol_state ( parent_commitment) ?
361- . ok_or ( WorkerError :: MissingPreState ( parent_commitment) ) ?;
362- let parent_state = MemoryStateBaseLayer :: from_container ( parent_state_raw) ;
392+ let parent_state = fetch_parent_state ( ctx, parent_commitment) ?;
393+ validate_block_inputs ( spec, ctx, block, parent_header, & parent_state) ?;
363394
364395 // Execute and extract outputs
365396 let ( write_batch, indexer_writes, logs) =
0 commit comments