From dd296cbd8a4464fa0cee46cc1cf60ef9f8c58991 Mon Sep 17 00:00:00 2001 From: terencechain Date: Sat, 11 Jun 2022 10:37:37 -0700 Subject: [PATCH] Disallow lower justified epoch to override higher epoch (#10865) --- .../precompute/justification_finalization.go | 12 ++++++------ .../precompute/justification_finalization_test.go | 15 +++++++++++++++ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/beacon-chain/core/epoch/precompute/justification_finalization.go b/beacon-chain/core/epoch/precompute/justification_finalization.go index 0f01a027f..374638a5c 100644 --- a/beacon-chain/core/epoch/precompute/justification_finalization.go +++ b/beacon-chain/core/epoch/precompute/justification_finalization.go @@ -25,7 +25,7 @@ func UnrealizedCheckpoints(st state.BeaconState) (*ethpb.Checkpoint, *ethpb.Chec } justification := processJustificationBits(st, activeBalance, prevTarget, currentTarget) - return computeCheckpoints(st, justification) + return ComputeCheckpoints(st, justification) } // ProcessJustificationAndFinalizationPreCompute processes justification and finalization during @@ -77,7 +77,7 @@ func processJustificationBits(state state.BeaconState, totalActiveBalance, prevE // updateJustificationAndFinalization processes justification and finalization during // epoch processing. This is where a beacon node can justify and finalize a new epoch. func weighJustificationAndFinalization(state state.BeaconState, newBits bitfield.Bitvector4) (state.BeaconState, error) { - jc, fc, err := computeCheckpoints(state, newBits) + jc, fc, err := ComputeCheckpoints(state, newBits) if err != nil { return nil, err } @@ -100,7 +100,7 @@ func weighJustificationAndFinalization(state state.BeaconState, newBits bitfield return state, nil } -// computeCheckpoints computes the new Justification and Finalization +// ComputeCheckpoints computes the new Justification and Finalization // checkpoints at epoch transition // Spec pseudocode definition: // def weigh_justification_and_finalization(state: BeaconState, @@ -139,7 +139,7 @@ func weighJustificationAndFinalization(state state.BeaconState, newBits bitfield // # The 1st/2nd most recent epochs are justified, the 1st using the 2nd as source // if all(bits[0:2]) and old_current_justified_checkpoint.epoch + 1 == current_epoch: // state.finalized_checkpoint = old_current_justified_checkpoint -func computeCheckpoints(state state.BeaconState, newBits bitfield.Bitvector4) (*ethpb.Checkpoint, *ethpb.Checkpoint, error) { +func ComputeCheckpoints(state state.BeaconState, newBits bitfield.Bitvector4) (*ethpb.Checkpoint, *ethpb.Checkpoint, error) { prevEpoch := time.PrevEpoch(state) currentEpoch := time.CurrentEpoch(state) oldPrevJustifiedCheckpoint := state.PreviousJustifiedCheckpoint() @@ -149,14 +149,14 @@ func computeCheckpoints(state state.BeaconState, newBits bitfield.Bitvector4) (* finalizedCheckpoint := state.FinalizedCheckpoint() // If 2/3 or more of the total balance attested in the current epoch. - if newBits.BitAt(0) { + if newBits.BitAt(0) && currentEpoch >= justifiedCheckpoint.Epoch { blockRoot, err := helpers.BlockRoot(state, currentEpoch) if err != nil { return nil, nil, errors.Wrapf(err, "could not get block root for current epoch %d", currentEpoch) } justifiedCheckpoint.Epoch = currentEpoch justifiedCheckpoint.Root = blockRoot - } else if newBits.BitAt(1) { + } else if newBits.BitAt(1) && prevEpoch >= justifiedCheckpoint.Epoch { // If 2/3 or more of total balance attested in the previous epoch. blockRoot, err := helpers.BlockRoot(state, prevEpoch) if err != nil { diff --git a/beacon-chain/core/epoch/precompute/justification_finalization_test.go b/beacon-chain/core/epoch/precompute/justification_finalization_test.go index e8cdc2b1f..90172576e 100644 --- a/beacon-chain/core/epoch/precompute/justification_finalization_test.go +++ b/beacon-chain/core/epoch/precompute/justification_finalization_test.go @@ -250,3 +250,18 @@ func TestUnrealizedCheckpoints(t *testing.T) { }) } } + +func Test_ComputeCheckpoints_CantUpdateToLower(t *testing.T) { + st, err := v2.InitializeFromProto(ðpb.BeaconStateAltair{ + Slot: params.BeaconConfig().SlotsPerEpoch * 2, + CurrentJustifiedCheckpoint: ðpb.Checkpoint{ + Epoch: 2, + }, + }) + require.NoError(t, err) + jb := make(bitfield.Bitvector4, 1) + jb.SetBitAt(1, true) + cp, _, err := precompute.ComputeCheckpoints(st, jb) + require.NoError(t, err) + require.Equal(t, types.Epoch(2), cp.Epoch) +}