diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go index 93b879e8e7e0..f354f14e5c20 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go @@ -115,13 +115,7 @@ func (vs *Server) GetBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) ( return vs.constructGenericBeaconBlock(sBlk, bundleCache.get(req.Slot)) } -func (vs *Server) handleFailedReorgAttempt(ctx context.Context, slot primitives.Slot, parentRoot, headRoot [32]byte) (state.BeaconState, error) { - blockchain.LateBlockAttemptedReorgCount.Inc() - log.WithFields(logrus.Fields{ - "slot": slot, - "parentRoot": fmt.Sprintf("%#x", parentRoot), - "headRoot": fmt.Sprintf("%#x", headRoot), - }).Warn("late block attempted reorg failed") +func (vs *Server) handleSuccesfulReorgAttempt(ctx context.Context, slot primitives.Slot, parentRoot, headRoot [32]byte) (state.BeaconState, error) { // Try to get the state from the NSC head := transition.NextSlotState(parentRoot[:], slot) if head != nil { @@ -135,7 +129,16 @@ func (vs *Server) handleFailedReorgAttempt(ctx context.Context, slot primitives. return head, nil } -func (vs *Server) getHeadNoFailedReorg(ctx context.Context, slot primitives.Slot, parentRoot [32]byte) (state.BeaconState, error) { +func logFailedReorgAttempt(slot primitives.Slot, oldHeadRoot, headRoot [32]byte) { + blockchain.LateBlockAttemptedReorgCount.Inc() + log.WithFields(logrus.Fields{ + "slot": slot, + "oldHeadRoot": fmt.Sprintf("%#x", oldHeadRoot), + "headRoot": fmt.Sprintf("%#x", headRoot), + }).Warn("late block attempted reorg failed") +} + +func (vs *Server) getHeadNoReorg(ctx context.Context, slot primitives.Slot, parentRoot [32]byte) (state.BeaconState, error) { // Try to get the state from the NSC head := transition.NextSlotState(parentRoot[:], slot) if head != nil { @@ -148,11 +151,14 @@ func (vs *Server) getHeadNoFailedReorg(ctx context.Context, slot primitives.Slot return head, nil } -func (vs *Server) getParentStateFromReorgData(ctx context.Context, slot primitives.Slot, parentRoot, headRoot [32]byte) (head state.BeaconState, err error) { +func (vs *Server) getParentStateFromReorgData(ctx context.Context, slot primitives.Slot, oldHeadRoot, parentRoot, headRoot [32]byte) (head state.BeaconState, err error) { if parentRoot != headRoot { - head, err = vs.handleFailedReorgAttempt(ctx, slot, parentRoot, headRoot) + head, err = vs.handleSuccesfulReorgAttempt(ctx, slot, parentRoot, headRoot) } else { - head, err = vs.getHeadNoFailedReorg(ctx, slot, parentRoot) + if oldHeadRoot != headRoot { + logFailedReorgAttempt(slot, oldHeadRoot, headRoot) + } + head, err = vs.getHeadNoReorg(ctx, slot, parentRoot) } if err != nil { return nil, err @@ -169,10 +175,11 @@ func (vs *Server) getParentStateFromReorgData(ctx context.Context, slot primitiv func (vs *Server) getParentState(ctx context.Context, slot primitives.Slot) (state.BeaconState, [32]byte, error) { // process attestations and update head in forkchoice + oldHeadRoot := vs.ForkchoiceFetcher.CachedHeadRoot() vs.ForkchoiceFetcher.UpdateHead(ctx, vs.TimeFetcher.CurrentSlot()) headRoot := vs.ForkchoiceFetcher.CachedHeadRoot() parentRoot := vs.ForkchoiceFetcher.GetProposerHead() - head, err := vs.getParentStateFromReorgData(ctx, slot, parentRoot, headRoot) + head, err := vs.getParentStateFromReorgData(ctx, slot, oldHeadRoot, parentRoot, headRoot) return head, parentRoot, err } diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_test.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_test.go index f9aa94e33900..16be3504ef21 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_test.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_test.go @@ -2874,8 +2874,8 @@ func TestProposer_GetParentHeadState(t *testing.T) { Eth1BlockFetcher: &mockExecution.Chain{}, StateGen: stategen.New(db, doublylinkedtree.New()), } - t.Run("failed reorg", func(tt *testing.T) { - head, err := proposerServer.getParentStateFromReorgData(ctx, 1, parentRoot, headRoot) + t.Run("successful reorg", func(tt *testing.T) { + head, err := proposerServer.getParentStateFromReorgData(ctx, 1, parentRoot, parentRoot, headRoot) require.NoError(t, err) st := parentState.Copy() st, err = transition.ProcessSlots(ctx, st, st.Slot()+1) @@ -2892,7 +2892,25 @@ func TestProposer_GetParentHeadState(t *testing.T) { t.Run("no reorg", func(tt *testing.T) { require.NoError(t, transition.UpdateNextSlotCache(ctx, headRoot[:], headState)) - head, err := proposerServer.getParentStateFromReorgData(ctx, 1, headRoot, headRoot) + head, err := proposerServer.getParentStateFromReorgData(ctx, 1, headRoot, headRoot, headRoot) + require.NoError(t, err) + st := headState.Copy() + st, err = transition.ProcessSlots(ctx, st, st.Slot()+1) + require.NoError(t, err) + str, err := st.StateRootAtIndex(0) + require.NoError(t, err) + headStr, err := head.StateRootAtIndex(0) + require.NoError(t, err) + genesisStr, err := parentState.StateRootAtIndex(0) + require.NoError(t, err) + require.Equal(t, [32]byte(str), [32]byte(headStr)) + require.NotEqual(t, [32]byte(str), [32]byte(genesisStr)) + }) + + t.Run("failed reorg", func(tt *testing.T) { + hook := logTest.NewGlobal() + require.NoError(t, transition.UpdateNextSlotCache(ctx, headRoot[:], headState)) + head, err := proposerServer.getParentStateFromReorgData(ctx, 1, parentRoot, headRoot, headRoot) require.NoError(t, err) st := headState.Copy() st, err = transition.ProcessSlots(ctx, st, st.Slot()+1) @@ -2905,5 +2923,6 @@ func TestProposer_GetParentHeadState(t *testing.T) { require.NoError(t, err) require.Equal(t, [32]byte(str), [32]byte(headStr)) require.NotEqual(t, [32]byte(str), [32]byte(genesisStr)) + require.LogsContain(t, hook, "late block attempted reorg failed") }) }