@@ -90,7 +90,6 @@ pub const ForkChoiceError = ProtoArrayError || error{
9090 ForkChoiceStoreErr ,
9191 UnableToSetJustifiedCheckpoint ,
9292 AfterBlockFailed ,
93- GenesisBlockNotAvailable ,
9493 DependentRootNotFound ,
9594};
9695
@@ -118,6 +117,13 @@ pub const AncestorStatus = enum {
118117};
119118
120119/// Result of `getCommonAncestorDepth`: ancestor status + optional depth.
120+ /// Result of `getAllAncestorAndNonAncestorBlocks`: owned slices of ancestor
121+ /// and non-ancestor proto-blocks partitioned by the finalized checkpoint.
122+ pub const AncestorAndNonAncestorBlocks = struct {
123+ ancestors : []ProtoBlock ,
124+ non_ancestors : []ProtoBlock ,
125+ };
126+
121127pub const AncestorResult = union (AncestorStatus ) {
122128 common_ancestor : struct { depth : u32 },
123129 descendant : void ,
@@ -1559,7 +1565,7 @@ pub const ForkChoice = struct {
15591565
15601566 /// Propagate execution layer validity response through the DAG.
15611567 /// Only sets irrecoverable_error for InvalidLVHExecutionResponse;
1562- /// other errors are silently ignored (matching TS behavior) .
1568+ /// other errors are silently ignored.
15631569 pub fn validateLatestHash (
15641570 self : * ForkChoice ,
15651571 allocator : Allocator ,
@@ -1641,8 +1647,8 @@ pub const ForkChoice = struct {
16411647 /// no fork-check is performed inside this function.
16421648 ///
16431649 /// Spec: https://github.com/ethereum/consensus-specs/blob/v1.6.0/fork_choice/safe-block.md#get_safe_execution_block_hash
1644- pub fn getSafeExecutionBlockHash (self : * const ForkChoice ) Root {
1645- const justified_block = self .getJustifiedBlock () catch return ZERO_HASH ;
1650+ pub fn getSafeExecutionBlockHash (self : * const ForkChoice ) ! Root {
1651+ const justified_block = try self .getJustifiedBlock ();
16461652 return justified_block .extra_meta .executionPayloadBlockHash () orelse ZERO_HASH ;
16471653 }
16481654
@@ -1760,7 +1766,7 @@ pub const ForkChoice = struct {
17601766 allocator : Allocator ,
17611767 block_root : Root ,
17621768 status : PayloadStatus ,
1763- ) ! struct { ancestors : [] ProtoBlock , non_ancestors : [] ProtoBlock } {
1769+ ) ! AncestorAndNonAncestorBlocks {
17641770 var pa_result = try self .proto_array .getAllAncestorAndNonAncestorNodes (allocator , block_root , status );
17651771 // The last ancestor block is the previous finalized one, exclude it.
17661772 if (pa_result .ancestors .items .len > 0 ) _ = pa_result .ancestors .pop ();
@@ -1801,9 +1807,11 @@ pub const ForkChoice = struct {
18011807 @as (i64 , @intCast (epoch_diff_val * preset .SLOTS_PER_EPOCH ));
18021808
18031809 // Special case close to genesis block, return the genesis block root.
1810+ // Invariant: when before_slot <= 0, genesis has not been pruned yet
1811+ // (finalization hasn't advanced enough), so items[0] is always genesis.
18041812 if (before_slot_signed <= 0 ) {
18051813 const genesis_block = & self .proto_array .nodes .items [0 ];
1806- if (genesis_block .slot != 0 ) return error . GenesisBlockNotAvailable ;
1814+ assert (genesis_block .slot == 0 );
18071815 return genesis_block .block_root ;
18081816 }
18091817 const before_slot : Slot = @intCast (before_slot_signed );
@@ -2027,7 +2035,7 @@ fn getCheckpointPayloadStatus(state: *CachedBeaconState, checkpoint_epoch: Epoch
20272035 const fork = state .config .forkSeq (checkpoint_slot );
20282036
20292037 // Pre-Gloas: always FULL.
2030- if (! fork .gte (.gloas )) return .full ;
2038+ if (fork .lt (.gloas )) return .full ;
20312039
20322040 // For Gloas, check state.execution_payload_availability.
20332041 const payload_available = state .state .executionPayloadAvailability (
0 commit comments