diff --git a/beacon-chain/rpc/core/validator.go b/beacon-chain/rpc/core/validator.go index 7092a6979f7c..9a5663bbfcad 100644 --- a/beacon-chain/rpc/core/validator.go +++ b/beacon-chain/rpc/core/validator.go @@ -401,7 +401,19 @@ func (s *Service) GetAttestationData( if err != nil { return nil, &RpcError{Reason: Internal, Err: errors.Wrap(err, "could not get target root")} } - justifiedCheckpoint := s.FinalizedFetcher.CurrentJustifiedCheckpt() + + headState, err := s.HeadFetcher.HeadState(ctx) + if err != nil { + return nil, &RpcError{Reason: Internal, Err: errors.Wrap(err, "could not get head state")} + } + if coreTime.CurrentEpoch(headState) < slots.ToEpoch(req.Slot) { // Ensure justified checkpoint safety by processing head state across the boundary. + headState, err = transition.ProcessSlotsUsingNextSlotCache(ctx, headState, headRoot, req.Slot) + if err != nil { + return nil, &RpcError{Reason: Internal, Err: errors.Errorf("could not process slots up to %d: %v", req.Slot, err)} + } + } + justifiedCheckpoint := headState.CurrentJustifiedCheckpoint() + if err = s.AttestationCache.Put(&cache.AttestationConsensusData{ Slot: req.Slot, HeadRoot: headRoot, diff --git a/beacon-chain/rpc/eth/validator/handlers_test.go b/beacon-chain/rpc/eth/validator/handlers_test.go index bf41243930a7..178d6fcb0c00 100644 --- a/beacon-chain/rpc/eth/validator/handlers_test.go +++ b/beacon-chain/rpc/eth/validator/handlers_test.go @@ -838,10 +838,14 @@ func TestGetAttestationData(t *testing.T) { justifiedRoot, err := justifiedBlock.Block.HashTreeRoot() require.NoError(t, err, "Could not get signing root for justified block") slot := 3*params.BeaconConfig().SlotsPerEpoch + 1 + beaconState, err := util.NewBeaconState() + require.NoError(t, err) + require.NoError(t, beaconState.SetSlot(slot)) justifiedCheckpoint := ðpbalpha.Checkpoint{ Epoch: 2, Root: justifiedRoot[:], } + require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(justifiedCheckpoint)) offset := int64(slot.Mul(params.BeaconConfig().SecondsPerSlot)) chain := &mockChain.ChainService{ Optimistic: false, @@ -849,6 +853,7 @@ func TestGetAttestationData(t *testing.T) { Root: blockRoot[:], CurrentJustifiedCheckPoint: justifiedCheckpoint, TargetRoot: blockRoot, + State: beaconState, } s := &Server{ @@ -1076,10 +1081,14 @@ func TestGetAttestationData(t *testing.T) { justifiedRoot, err := justifiedBlock.Block.HashTreeRoot() require.NoError(t, err, "Could not get signing root for justified block") + beaconState, err := util.NewBeaconState() + require.NoError(t, err) + require.NoError(t, beaconState.SetSlot(slot)) justifiedCheckpt := ðpbalpha.Checkpoint{ Epoch: 0, Root: justifiedRoot[:], } + require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(justifiedCheckpt)) require.NoError(t, err) offset := int64(slot.Mul(params.BeaconConfig().SecondsPerSlot)) chain := &mockChain.ChainService{ @@ -1087,6 +1096,7 @@ func TestGetAttestationData(t *testing.T) { Genesis: time.Now().Add(time.Duration(-1*offset) * time.Second), CurrentJustifiedCheckPoint: justifiedCheckpt, TargetRoot: blockRoot, + State: beaconState, } s := &Server{ @@ -1163,17 +1173,24 @@ func TestGetAttestationData(t *testing.T) { require.NoError(t, err, "Could not hash beacon block") justifiedBlockRoot, err := justifiedBlock.Block.HashTreeRoot() require.NoError(t, err, "Could not hash justified block") + + slot := primitives.Slot(10000) + beaconState, err := util.NewBeaconState() + require.NoError(t, err) + require.NoError(t, beaconState.SetSlot(slot)) justifiedCheckpt := ðpbalpha.Checkpoint{ Epoch: slots.ToEpoch(1500), Root: justifiedBlockRoot[:], } - slot := primitives.Slot(10000) + require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(justifiedCheckpt)) + offset := int64(slot.Mul(params.BeaconConfig().SecondsPerSlot)) chain := &mockChain.ChainService{ Root: blockRoot[:], Genesis: time.Now().Add(time.Duration(-1*offset) * time.Second), CurrentJustifiedCheckPoint: justifiedCheckpt, TargetRoot: blockRoot, + State: beaconState, } s := &Server{ diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/attester_mainnet_test.go b/beacon-chain/rpc/prysm/v1alpha1/validator/attester_mainnet_test.go index 4c177882e5a3..3d05ef48ca80 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/attester_mainnet_test.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/attester_mainnet_test.go @@ -49,12 +49,16 @@ func TestAttestationDataAtSlot_HandlesFarAwayJustifiedEpoch(t *testing.T) { justifiedBlockRoot, err := justifiedBlock.Block.HashTreeRoot() require.NoError(t, err, "Could not hash justified block") + slot := primitives.Slot(10000) + beaconState, err := util.NewBeaconState() + require.NoError(t, err) + require.NoError(t, beaconState.SetSlot(slot)) justifiedCheckpoint := ðpb.Checkpoint{ Epoch: slots.ToEpoch(1500), Root: justifiedBlockRoot[:], } - require.NoError(t, err) - slot := primitives.Slot(10000) + require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(justifiedCheckpoint)) + offset := int64(slot.Mul(params.BeaconConfig().SecondsPerSlot)) attesterServer := &Server{ SyncChecker: &mockSync.Sync{IsSyncing: false}, @@ -62,7 +66,7 @@ func TestAttestationDataAtSlot_HandlesFarAwayJustifiedEpoch(t *testing.T) { TimeFetcher: &mock.ChainService{Genesis: time.Now().Add(time.Duration(-1*offset) * time.Second)}, CoreService: &core.Service{ AttestationCache: cache.NewAttestationCache(), - HeadFetcher: &mock.ChainService{TargetRoot: blockRoot, Root: blockRoot[:]}, + HeadFetcher: &mock.ChainService{TargetRoot: blockRoot, Root: blockRoot[:], State: beaconState}, GenesisTimeFetcher: &mock.ChainService{Genesis: time.Now().Add(time.Duration(-1*offset) * time.Second)}, FinalizedFetcher: &mock.ChainService{CurrentJustifiedCheckPoint: justifiedCheckpoint}, OptimisticModeFetcher: &mock.ChainService{Optimistic: false}, diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/attester_test.go b/beacon-chain/rpc/prysm/v1alpha1/validator/attester_test.go index 53e331deb0b8..e3d10f92ec67 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/attester_test.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/attester_test.go @@ -102,17 +102,21 @@ func TestGetAttestationData_OK(t *testing.T) { justifiedRoot, err := justifiedBlock.Block.HashTreeRoot() require.NoError(t, err, "Could not get signing root for justified block") slot := 3*params.BeaconConfig().SlotsPerEpoch + 1 + beaconState, err := util.NewBeaconState() + require.NoError(t, err) + require.NoError(t, beaconState.SetSlot(slot)) justifiedCheckpoint := ðpb.Checkpoint{ Epoch: 2, Root: justifiedRoot[:], } + require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(justifiedCheckpoint)) offset := int64(slot.Mul(params.BeaconConfig().SecondsPerSlot)) attesterServer := &Server{ SyncChecker: &mockSync.Sync{IsSyncing: false}, OptimisticModeFetcher: &mock.ChainService{Optimistic: false}, TimeFetcher: &mock.ChainService{Genesis: time.Now().Add(time.Duration(-1*offset) * time.Second)}, CoreService: &core.Service{ - HeadFetcher: &mock.ChainService{TargetRoot: targetRoot, Root: blockRoot[:]}, + HeadFetcher: &mock.ChainService{TargetRoot: targetRoot, Root: blockRoot[:], State: beaconState}, GenesisTimeFetcher: &mock.ChainService{ Genesis: time.Now().Add(time.Duration(-1*offset) * time.Second), }, @@ -338,10 +342,15 @@ func TestGetAttestationData_SucceedsInFirstEpoch(t *testing.T) { targetRoot, err := targetBlock.Block.HashTreeRoot() require.NoError(t, err, "Could not get signing root for target block") + beaconState, err := util.NewBeaconState() + require.NoError(t, err) + require.NoError(t, beaconState.SetSlot(slot)) justifiedCheckpoint := ðpb.Checkpoint{ Epoch: 0, Root: justifiedRoot[:], } + require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(justifiedCheckpoint)) + offset := int64(slot.Mul(params.BeaconConfig().SecondsPerSlot)) attesterServer := &Server{ SyncChecker: &mockSync.Sync{IsSyncing: false}, @@ -350,7 +359,7 @@ func TestGetAttestationData_SucceedsInFirstEpoch(t *testing.T) { CoreService: &core.Service{ AttestationCache: cache.NewAttestationCache(), HeadFetcher: &mock.ChainService{ - TargetRoot: targetRoot, Root: blockRoot[:], + TargetRoot: targetRoot, Root: blockRoot[:], State: beaconState, }, GenesisTimeFetcher: &mock.ChainService{Genesis: prysmTime.Now().Add(time.Duration(-1*offset) * time.Second)}, FinalizedFetcher: &mock.ChainService{CurrentJustifiedCheckPoint: justifiedCheckpoint},