@@ -442,3 +442,136 @@ func TestBlockInclusion(t *testing.T) {
442442 require .Empty (t , missed )
443443 })
444444}
445+
446+ func TestInclusion404Handling (t * testing.T ) {
447+ ctx := context .Background ()
448+
449+ t .Run ("checkBlock handles 404 error gracefully" , func (t * testing.T ) {
450+ bmock , err := beaconmock .New (ctx )
451+ require .NoError (t , err )
452+
453+ // Mock SignedBeaconBlock to return a 404 error
454+ bmock .SignedBeaconBlockFunc = func (ctx context.Context , blockID string ) (* eth2spec.VersionedSignedBeaconBlock , error ) {
455+ return nil , & eth2api.Error {
456+ StatusCode : 404 ,
457+ Method : "GET" ,
458+ Endpoint : "/eth/v2/beacon/blocks/" + blockID ,
459+ Data : []byte (`{"code":404,"message":"NOT_FOUND: beacon block not found"}` ),
460+ }
461+ }
462+
463+ // Wrap beaconmock with eth2wrap to get proper error handling
464+ eth2Cl , err := eth2wrap .Instrument ([]eth2wrap.Client {bmock }, nil )
465+ require .NoError (t , err )
466+
467+ var (
468+ checkBlockCalled bool
469+ foundBlock bool
470+ )
471+
472+ noopTrackerInclFunc := func (duty core.Duty , key core.PubKey , data core.SignedData , err error ) {}
473+
474+ incl , err := NewInclusion (ctx , eth2Cl , noopTrackerInclFunc )
475+ require .NoError (t , err )
476+
477+ // Override checkBlockFunc to capture the result
478+ incl .checkBlockFunc = func (ctx context.Context , slot uint64 , found bool ) {
479+ checkBlockCalled = true
480+ foundBlock = found
481+ }
482+
483+ // Call checkBlock with a slot that will trigger the 404
484+ err = incl .checkBlock (ctx , 12345 , nil )
485+ require .NoError (t , err , "checkBlock should not return an error for 404" )
486+ require .True (t , checkBlockCalled , "checkBlockFunc should have been called" )
487+ require .False (t , foundBlock , "block should be marked as not found" )
488+ })
489+
490+ t .Run ("checkBlockAndAtts handles 404 error gracefully" , func (t * testing.T ) {
491+ featureset .EnableForT (t , featureset .AttestationInclusion )
492+
493+ bmock , err := beaconmock .New (ctx )
494+ require .NoError (t , err )
495+
496+ // Mock BeaconBlockAttestations to return a 404 error
497+ bmock .BeaconBlockAttestationsFunc = func (ctx context.Context , opts * eth2api.BeaconBlockAttestationsOpts ) ([]* eth2spec.VersionedAttestation , error ) {
498+ return nil , & eth2api.Error {
499+ StatusCode : 404 ,
500+ Method : "GET" ,
501+ Endpoint : "/eth/v1/beacon/blocks/" + opts .Block + "/attestations" ,
502+ Data : []byte (`{"code":404,"message":"NOT_FOUND: beacon block not found"}` ),
503+ }
504+ }
505+
506+ // Wrap beaconmock with eth2wrap to get proper error handling
507+ eth2Cl , err := eth2wrap .Instrument ([]eth2wrap.Client {bmock }, nil )
508+ require .NoError (t , err )
509+
510+ noopTrackerInclFunc := func (duty core.Duty , key core.PubKey , data core.SignedData , err error ) {}
511+
512+ incl , err := NewInclusion (ctx , eth2Cl , noopTrackerInclFunc )
513+ require .NoError (t , err )
514+
515+ // Call checkBlockAndAtts with a slot that will trigger the 404
516+ err = incl .checkBlockAndAtts (ctx , 12345 , nil )
517+ require .NoError (t , err , "checkBlockAndAtts should not return an error for 404" )
518+ })
519+
520+ t .Run ("checkBlock returns error for non-404 errors" , func (t * testing.T ) {
521+ bmock , err := beaconmock .New (ctx )
522+ require .NoError (t , err )
523+
524+ // Mock SignedBeaconBlock to return a 500 error
525+ bmock .SignedBeaconBlockFunc = func (ctx context.Context , blockID string ) (* eth2spec.VersionedSignedBeaconBlock , error ) {
526+ return nil , & eth2api.Error {
527+ StatusCode : 500 ,
528+ Method : "GET" ,
529+ Endpoint : "/eth/v2/beacon/blocks/" + blockID ,
530+ Data : []byte (`{"code":500,"message":"Internal server error"}` ),
531+ }
532+ }
533+
534+ // Wrap beaconmock with eth2wrap to get proper error handling
535+ eth2Cl , err := eth2wrap .Instrument ([]eth2wrap.Client {bmock }, nil )
536+ require .NoError (t , err )
537+
538+ noopTrackerInclFunc := func (duty core.Duty , key core.PubKey , data core.SignedData , err error ) {}
539+
540+ incl , err := NewInclusion (ctx , eth2Cl , noopTrackerInclFunc )
541+ require .NoError (t , err )
542+
543+ // Call checkBlock with a slot that will trigger the 500 error
544+ err = incl .checkBlock (ctx , 12345 , nil )
545+ require .Error (t , err , "checkBlock should return an error for non-404 errors" )
546+ })
547+
548+ t .Run ("checkBlockAndAtts returns error for non-404 errors" , func (t * testing.T ) {
549+ featureset .EnableForT (t , featureset .AttestationInclusion )
550+
551+ bmock , err := beaconmock .New (ctx )
552+ require .NoError (t , err )
553+
554+ // Mock BeaconBlockAttestations to return a 500 error
555+ bmock .BeaconBlockAttestationsFunc = func (ctx context.Context , opts * eth2api.BeaconBlockAttestationsOpts ) ([]* eth2spec.VersionedAttestation , error ) {
556+ return nil , & eth2api.Error {
557+ StatusCode : 500 ,
558+ Method : "GET" ,
559+ Endpoint : "/eth/v1/beacon/blocks/" + opts .Block + "/attestations" ,
560+ Data : []byte (`{"code":500,"message":"Internal server error"}` ),
561+ }
562+ }
563+
564+ // Wrap beaconmock with eth2wrap to get proper error handling
565+ eth2Cl , err := eth2wrap .Instrument ([]eth2wrap.Client {bmock }, nil )
566+ require .NoError (t , err )
567+
568+ noopTrackerInclFunc := func (duty core.Duty , key core.PubKey , data core.SignedData , err error ) {}
569+
570+ incl , err := NewInclusion (ctx , eth2Cl , noopTrackerInclFunc )
571+ require .NoError (t , err )
572+
573+ // Call checkBlockAndAtts with a slot that will trigger the 500 error
574+ err = incl .checkBlockAndAtts (ctx , 12345 , nil )
575+ require .Error (t , err , "checkBlockAndAtts should return an error for non-404 errors" )
576+ })
577+ }
0 commit comments