From e20981bd531f9de98f313b99a59bdfa9e93df644 Mon Sep 17 00:00:00 2001 From: Potuz Date: Thu, 21 Apr 2022 17:36:03 +0200 Subject: [PATCH 01/28] unrealized justification API --- beacon-chain/core/altair/epoch_precompute.go | 41 +++++++++++- .../core/epoch/precompute/BUILD.bazel | 1 + .../precompute/justification_finalization.go | 67 ++++++++++--------- 3 files changed, 76 insertions(+), 33 deletions(-) diff --git a/beacon-chain/core/altair/epoch_precompute.go b/beacon-chain/core/altair/epoch_precompute.go index 16eb95bcc59b..f9bfb567f50f 100644 --- a/beacon-chain/core/altair/epoch_precompute.go +++ b/beacon-chain/core/altair/epoch_precompute.go @@ -10,6 +10,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/state" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/math" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/runtime/version" "go.opencensus.io/trace" ) @@ -48,7 +49,7 @@ func InitializePrecomputeValidators(ctx context.Context, beaconState state.Beaco return err } } - // Set validator's active status for preivous epoch. + // Set validator's active status for previous epoch. if helpers.IsActiveValidatorUsingTrie(val, prevEpoch) { v.IsActivePrevEpoch = true bal.ActivePrevEpoch, err = math.Add64(bal.ActivePrevEpoch, val.EffectiveBalance()) @@ -351,3 +352,41 @@ func attestationDelta( return reward, penalty, nil } + +// UnrealizedJustificationCheckpoint returns the justification checkpoint of the +// given state as if it was progressed with empty slots until the next epoch. +func UnrealizedJustificationCheckpoint(ctx context.Context, state state.BeaconStateAltair) (*ethpb.Checkpoint, error) { + if state == nil || state.IsNil() { + return nil, errors.New("nil state") + } + + prevEpoch := time.PrevEpoch(state) + currentEpoch := time.CurrentEpoch(state) + + vp, bp, err := InitializePrecomputeValidators(ctx, state) + if err != nil { + return nil, err + } + + // New in Altair. + _, bp, err = ProcessEpochParticipation(ctx, state, bp, vp) + if err != nil { + return nil, err + } + justification := precompute.ProcessJustificationBits(state, bp.ActiveCurrentEpoch, bp.PrevEpochTargetAttested, bp.CurrentEpochTargetAttested) + if justification.BitAt(0) { + blockRoot, err := helpers.BlockRoot(state, currentEpoch) + if err != nil { + return nil, errors.Wrapf(err, "could not get block root for current epoch %d", prevEpoch) + } + return ðpb.Checkpoint{Epoch: currentEpoch, Root: blockRoot}, nil + } + if justification.BitAt(1) { + blockRoot, err := helpers.BlockRoot(state, prevEpoch) + if err != nil { + return nil, errors.Wrapf(err, "could not get block root for previous epoch %d", prevEpoch) + } + return ðpb.Checkpoint{Epoch: prevEpoch, Root: blockRoot}, nil + } + return state.CurrentJustifiedCheckpoint(), nil +} diff --git a/beacon-chain/core/epoch/precompute/BUILD.bazel b/beacon-chain/core/epoch/precompute/BUILD.bazel index a857eb7686b7..224080ca6d17 100644 --- a/beacon-chain/core/epoch/precompute/BUILD.bazel +++ b/beacon-chain/core/epoch/precompute/BUILD.bazel @@ -28,6 +28,7 @@ go_library( "//time/slots:go_default_library", "@com_github_pkg_errors//:go_default_library", "@com_github_prysmaticlabs_eth2_types//:go_default_library", + "@com_github_prysmaticlabs_go_bitfield//:go_default_library", "@io_opencensus_go//trace:go_default_library", ], ) diff --git a/beacon-chain/core/epoch/precompute/justification_finalization.go b/beacon-chain/core/epoch/precompute/justification_finalization.go index 1c71d233633a..832dbdf16ac1 100644 --- a/beacon-chain/core/epoch/precompute/justification_finalization.go +++ b/beacon-chain/core/epoch/precompute/justification_finalization.go @@ -2,6 +2,7 @@ package precompute import ( "github.com/pkg/errors" + "github.com/prysmaticlabs/go-bitfield" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/time" "github.com/prysmaticlabs/prysm/beacon-chain/state" @@ -34,7 +35,26 @@ func ProcessJustificationAndFinalizationPreCompute(state state.BeaconState, pBal return state, nil } - return weighJustificationAndFinalization(state, pBal.ActiveCurrentEpoch, pBal.PrevEpochTargetAttested, pBal.CurrentEpochTargetAttested) + newBits := ProcessJustificationBits(state, pBal.ActiveCurrentEpoch, pBal.PrevEpochTargetAttested, pBal.CurrentEpochTargetAttested) + + return weighJustificationAndFinalization(state, newBits) +} + +// ProcessJustificationBits processes the justification bits during epoch +// processing. +func ProcessJustificationBits(state state.BeaconState, totalActiveBalance, prevEpochTargetBalance, currEpochTargetBalance uint64) bitfield.Bitvector4 { + newBits := state.JustificationBits() + newBits.Shift(1) + // If 2/3 or more of total balance attested in the previous epoch. + if 3*prevEpochTargetBalance >= 2*totalActiveBalance { + newBits.SetBitAt(1, true) + } + + if 3*currEpochTargetBalance >= 2*totalActiveBalance { + newBits.SetBitAt(0, true) + } + + return newBits } // weighJustificationAndFinalization processes justification and finalization during @@ -77,8 +97,7 @@ func ProcessJustificationAndFinalizationPreCompute(state state.BeaconState, pBal // # 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 weighJustificationAndFinalization(state state.BeaconState, - totalActiveBalance, prevEpochTargetBalance, currEpochTargetBalance uint64) (state.BeaconState, error) { +func weighJustificationAndFinalization(state state.BeaconState, newBits bitfield.Bitvector4) (state.BeaconState, error) { prevEpoch := time.PrevEpoch(state) currentEpoch := time.CurrentEpoch(state) oldPrevJustifiedCheckpoint := state.PreviousJustifiedCheckpoint() @@ -88,33 +107,9 @@ func weighJustificationAndFinalization(state state.BeaconState, if err := state.SetPreviousJustifiedCheckpoint(state.CurrentJustifiedCheckpoint()); err != nil { return nil, err } - newBits := state.JustificationBits() - newBits.Shift(1) - if err := state.SetJustificationBits(newBits); err != nil { - return nil, err - } - - // Note: the spec refers to the bit index position starting at 1 instead of starting at zero. - // We will use that paradigm here for consistency with the godoc spec definition. - - // If 2/3 or more of total balance attested in the previous epoch. - if 3*prevEpochTargetBalance >= 2*totalActiveBalance { - blockRoot, err := helpers.BlockRoot(state, prevEpoch) - if err != nil { - return nil, errors.Wrapf(err, "could not get block root for previous epoch %d", prevEpoch) - } - if err := state.SetCurrentJustifiedCheckpoint(ðpb.Checkpoint{Epoch: prevEpoch, Root: blockRoot}); err != nil { - return nil, err - } - newBits := state.JustificationBits() - newBits.SetBitAt(1, true) - if err := state.SetJustificationBits(newBits); err != nil { - return nil, err - } - } // If 2/3 or more of the total balance attested in the current epoch. - if 3*currEpochTargetBalance >= 2*totalActiveBalance { + if newBits.BitAt(0) { blockRoot, err := helpers.BlockRoot(state, currentEpoch) if err != nil { return nil, errors.Wrapf(err, "could not get block root for current epoch %d", prevEpoch) @@ -122,15 +117,23 @@ func weighJustificationAndFinalization(state state.BeaconState, if err := state.SetCurrentJustifiedCheckpoint(ðpb.Checkpoint{Epoch: currentEpoch, Root: blockRoot}); err != nil { return nil, err } - newBits := state.JustificationBits() - newBits.SetBitAt(0, true) - if err := state.SetJustificationBits(newBits); err != nil { + } else if newBits.BitAt(1) { + // If 2/3 or more of total balance attested in the previous epoch. + blockRoot, err := helpers.BlockRoot(state, prevEpoch) + if err != nil { + return nil, errors.Wrapf(err, "could not get block root for previous epoch %d", prevEpoch) + } + if err := state.SetCurrentJustifiedCheckpoint(ðpb.Checkpoint{Epoch: prevEpoch, Root: blockRoot}); err != nil { return nil, err } } + if err := state.SetJustificationBits(newBits); err != nil { + return nil, err + } + // Process finalization according to Ethereum Beacon Chain specification. - justification := state.JustificationBits().Bytes()[0] + justification := newBits.Bytes()[0] // 2nd/3rd/4th (0b1110) most recent epochs are justified, the 2nd using the 4th as source. if justification&0x0E == 0x0E && (oldPrevJustifiedCheckpoint.Epoch+3) == currentEpoch { From e8e51d820b21a150cd12aa82c97cd80d3cc31b99 Mon Sep 17 00:00:00 2001 From: terence tsao Date: Thu, 21 Apr 2022 17:41:17 +0200 Subject: [PATCH 02/28] Add time elapse logging --- beacon-chain/blockchain/process_block.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/beacon-chain/blockchain/process_block.go b/beacon-chain/blockchain/process_block.go index 2ce93c9564a1..664ecea71d43 100644 --- a/beacon-chain/blockchain/process_block.go +++ b/beacon-chain/blockchain/process_block.go @@ -6,6 +6,7 @@ import ( "time" "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/beacon-chain/core/altair" "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks" "github.com/prysmaticlabs/prysm/beacon-chain/core/feed" statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state" @@ -109,6 +110,14 @@ func (s *Service) onBlock(ctx context.Context, signed block.SignedBeaconBlock, b if err != nil { return err } + + startTime := time.Now() + _, err = altair.UnrealizedJustificationCheckpoint(ctx, postState.Copy()) + if err != nil { + return err + } + log.WithField("duration", time.Since(startTime)).Info("Checked for unrealized justified checkpoint") + postStateVersion, postStateHeader, err := getStateVersionAndPayload(postState) if err != nil { return err From 771227c291304253d6a7c5f908543cdad2b75d1f Mon Sep 17 00:00:00 2001 From: Potuz Date: Thu, 21 Apr 2022 23:24:13 +0200 Subject: [PATCH 03/28] add unrealized justification checkpoint --- beacon-chain/core/altair/epoch_precompute.go | 54 ++++++++++++++++++-- 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/beacon-chain/core/altair/epoch_precompute.go b/beacon-chain/core/altair/epoch_precompute.go index f9bfb567f50f..cab156a5dcd4 100644 --- a/beacon-chain/core/altair/epoch_precompute.go +++ b/beacon-chain/core/altair/epoch_precompute.go @@ -4,6 +4,7 @@ import ( "context" "github.com/pkg/errors" + types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/time" @@ -362,18 +363,61 @@ func UnrealizedJustificationCheckpoint(ctx context.Context, state state.BeaconSt prevEpoch := time.PrevEpoch(state) currentEpoch := time.CurrentEpoch(state) - - vp, bp, err := InitializePrecomputeValidators(ctx, state) + activeBalance := uint64(0) + currentTarget := uint64(0) + prevTarget := uint64(0) + cp, err := state.CurrentEpochParticipation() if err != nil { return nil, err } - // New in Altair. - _, bp, err = ProcessEpochParticipation(ctx, state, bp, vp) + pp, err := state.PreviousEpochParticipation() if err != nil { return nil, err } - justification := precompute.ProcessJustificationBits(state, bp.ActiveCurrentEpoch, bp.PrevEpochTargetAttested, bp.CurrentEpochTargetAttested) + + cfg := params.BeaconConfig() + targetIdx := cfg.TimelyTargetFlagIndex + + for i := 0; i < state.NumValidators(); i++ { + val, err := state.ValidatorAtIndexReadOnly(types.ValidatorIndex(i)) + if err != nil { + return nil, err + } + if helpers.IsActiveValidatorUsingTrie(val, currentEpoch) && !val.Slashed() { + activeBalance, err = math.Add64(activeBalance, val.EffectiveBalance()) + if err != nil { + return nil, err + } + if i < len(cp) { + has, err := HasValidatorFlag(cp[i], targetIdx) + if err != nil { + return nil, err + } + if has { + currentTarget, err = math.Add64(currentTarget, val.EffectiveBalance()) + if err != nil { + return nil, err + } + } + } + + if i < len(pp) { + has, err := HasValidatorFlag(pp[i], targetIdx) + if err != nil { + return nil, err + } + if has { + prevTarget, err = math.Add64(prevTarget, val.EffectiveBalance()) + if err != nil { + return nil, err + } + } + } + } + } + + justification := precompute.ProcessJustificationBits(state, activeBalance, prevTarget, currentTarget) if justification.BitAt(0) { blockRoot, err := helpers.BlockRoot(state, currentEpoch) if err != nil { From 4250a4f4255133e16442c16924dfb468fec57d8b Mon Sep 17 00:00:00 2001 From: terence tsao Date: Sat, 23 Apr 2022 09:37:48 +0200 Subject: [PATCH 04/28] Use UnrealizedJustificationCheckpoint --- beacon-chain/core/altair/epoch_precompute.go | 66 +++++++++----------- 1 file changed, 30 insertions(+), 36 deletions(-) diff --git a/beacon-chain/core/altair/epoch_precompute.go b/beacon-chain/core/altair/epoch_precompute.go index cab156a5dcd4..564296435dc9 100644 --- a/beacon-chain/core/altair/epoch_precompute.go +++ b/beacon-chain/core/altair/epoch_precompute.go @@ -4,7 +4,6 @@ import ( "context" "github.com/pkg/errors" - types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/time" @@ -356,22 +355,23 @@ func attestationDelta( // UnrealizedJustificationCheckpoint returns the justification checkpoint of the // given state as if it was progressed with empty slots until the next epoch. -func UnrealizedJustificationCheckpoint(ctx context.Context, state state.BeaconStateAltair) (*ethpb.Checkpoint, error) { - if state == nil || state.IsNil() { +func UnrealizedJustificationCheckpoint(ctx context.Context, st state.BeaconStateAltair) (*ethpb.Checkpoint, error) { + if st == nil || st.IsNil() { return nil, errors.New("nil state") } - prevEpoch := time.PrevEpoch(state) - currentEpoch := time.CurrentEpoch(state) + prevEpoch := time.PrevEpoch(st) + currentEpoch := time.CurrentEpoch(st) activeBalance := uint64(0) currentTarget := uint64(0) prevTarget := uint64(0) - cp, err := state.CurrentEpochParticipation() + + cp, err := st.CurrentEpochParticipation() // TODO: Use read only if err != nil { return nil, err } - pp, err := state.PreviousEpochParticipation() + pp, err := st.PreviousEpochParticipation() if err != nil { return nil, err } @@ -379,58 +379,52 @@ func UnrealizedJustificationCheckpoint(ctx context.Context, state state.BeaconSt cfg := params.BeaconConfig() targetIdx := cfg.TimelyTargetFlagIndex - for i := 0; i < state.NumValidators(); i++ { - val, err := state.ValidatorAtIndexReadOnly(types.ValidatorIndex(i)) - if err != nil { - return nil, err - } + if err := st.ReadFromEveryValidator(func(idx int, val state.ReadOnlyValidator) error { if helpers.IsActiveValidatorUsingTrie(val, currentEpoch) && !val.Slashed() { activeBalance, err = math.Add64(activeBalance, val.EffectiveBalance()) if err != nil { - return nil, err + return err + } + has, err := HasValidatorFlag(cp[idx], targetIdx) + if err != nil { + return err } - if i < len(cp) { - has, err := HasValidatorFlag(cp[i], targetIdx) + if has { + currentTarget, err = math.Add64(currentTarget, val.EffectiveBalance()) if err != nil { - return nil, err - } - if has { - currentTarget, err = math.Add64(currentTarget, val.EffectiveBalance()) - if err != nil { - return nil, err - } + return err } } - - if i < len(pp) { - has, err := HasValidatorFlag(pp[i], targetIdx) + has, err = HasValidatorFlag(pp[idx], targetIdx) + if err != nil { + return err + } + if has { + prevTarget, err = math.Add64(prevTarget, val.EffectiveBalance()) if err != nil { - return nil, err - } - if has { - prevTarget, err = math.Add64(prevTarget, val.EffectiveBalance()) - if err != nil { - return nil, err - } + return err } } } + return nil + }); err != nil { + return nil, errors.Wrap(err, "could not read every validator") } - justification := precompute.ProcessJustificationBits(state, activeBalance, prevTarget, currentTarget) + justification := precompute.ProcessJustificationBits(st, activeBalance, prevTarget, currentTarget) if justification.BitAt(0) { - blockRoot, err := helpers.BlockRoot(state, currentEpoch) + blockRoot, err := helpers.BlockRoot(st, currentEpoch) if err != nil { return nil, errors.Wrapf(err, "could not get block root for current epoch %d", prevEpoch) } return ðpb.Checkpoint{Epoch: currentEpoch, Root: blockRoot}, nil } if justification.BitAt(1) { - blockRoot, err := helpers.BlockRoot(state, prevEpoch) + blockRoot, err := helpers.BlockRoot(st, prevEpoch) if err != nil { return nil, errors.Wrapf(err, "could not get block root for previous epoch %d", prevEpoch) } return ðpb.Checkpoint{Epoch: prevEpoch, Root: blockRoot}, nil } - return state.CurrentJustifiedCheckpoint(), nil + return st.CurrentJustifiedCheckpoint(), nil } From c3b67fddb8a7c39064217c672da8543595fe7df1 Mon Sep 17 00:00:00 2001 From: Potuz Date: Sun, 8 May 2022 13:45:54 -0300 Subject: [PATCH 05/28] Refactor unrealized checkpoints --- beacon-chain/blockchain/process_block.go | 9 --- beacon-chain/core/altair/BUILD.bazel | 1 + beacon-chain/core/altair/epoch_precompute.go | 30 ++------ .../core/altair/epoch_precompute_test.go | 10 +++ beacon-chain/core/altair/error.go | 5 ++ .../precompute/justification_finalization.go | 74 ++++++++++--------- 6 files changed, 64 insertions(+), 65 deletions(-) create mode 100644 beacon-chain/core/altair/error.go diff --git a/beacon-chain/blockchain/process_block.go b/beacon-chain/blockchain/process_block.go index c7c7711a71b0..e6db77c0321d 100644 --- a/beacon-chain/blockchain/process_block.go +++ b/beacon-chain/blockchain/process_block.go @@ -6,7 +6,6 @@ import ( "time" "github.com/pkg/errors" - "github.com/prysmaticlabs/prysm/beacon-chain/core/altair" "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks" "github.com/prysmaticlabs/prysm/beacon-chain/core/feed" statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state" @@ -111,14 +110,6 @@ func (s *Service) onBlock(ctx context.Context, signed interfaces.SignedBeaconBlo if err != nil { return err } - - startTime := time.Now() - _, err = altair.UnrealizedJustificationCheckpoint(ctx, postState.Copy()) - if err != nil { - return err - } - log.WithField("duration", time.Since(startTime)).Info("Checked for unrealized justified checkpoint") - postStateVersion, postStateHeader, err := getStateVersionAndPayload(postState) if err != nil { return err diff --git a/beacon-chain/core/altair/BUILD.bazel b/beacon-chain/core/altair/BUILD.bazel index c9ef984f3116..3cde01c2b71a 100644 --- a/beacon-chain/core/altair/BUILD.bazel +++ b/beacon-chain/core/altair/BUILD.bazel @@ -8,6 +8,7 @@ go_library( "deposit.go", "epoch_precompute.go", "epoch_spec.go", + "error.go", "reward.go", "sync_committee.go", "transition.go", diff --git a/beacon-chain/core/altair/epoch_precompute.go b/beacon-chain/core/altair/epoch_precompute.go index 564296435dc9..eae04477a40f 100644 --- a/beacon-chain/core/altair/epoch_precompute.go +++ b/beacon-chain/core/altair/epoch_precompute.go @@ -353,14 +353,12 @@ func attestationDelta( return reward, penalty, nil } -// UnrealizedJustificationCheckpoint returns the justification checkpoint of the +// UnrealizedCheckpoints returns the justification and finalization checkpoints of the // given state as if it was progressed with empty slots until the next epoch. -func UnrealizedJustificationCheckpoint(ctx context.Context, st state.BeaconStateAltair) (*ethpb.Checkpoint, error) { +func UnrealizedCheckpoints(ctx context.Context, st state.BeaconStateAltair) (*ethpb.Checkpoint, *ethpb.Checkpoint, error) { if st == nil || st.IsNil() { - return nil, errors.New("nil state") + return nil, nil, errNilState } - - prevEpoch := time.PrevEpoch(st) currentEpoch := time.CurrentEpoch(st) activeBalance := uint64(0) currentTarget := uint64(0) @@ -368,12 +366,12 @@ func UnrealizedJustificationCheckpoint(ctx context.Context, st state.BeaconState cp, err := st.CurrentEpochParticipation() // TODO: Use read only if err != nil { - return nil, err + return nil, nil, err } pp, err := st.PreviousEpochParticipation() if err != nil { - return nil, err + return nil, nil, err } cfg := params.BeaconConfig() @@ -408,23 +406,9 @@ func UnrealizedJustificationCheckpoint(ctx context.Context, st state.BeaconState } return nil }); err != nil { - return nil, errors.Wrap(err, "could not read every validator") + return nil, nil, errors.Wrap(err, "could not read every validator") } justification := precompute.ProcessJustificationBits(st, activeBalance, prevTarget, currentTarget) - if justification.BitAt(0) { - blockRoot, err := helpers.BlockRoot(st, currentEpoch) - if err != nil { - return nil, errors.Wrapf(err, "could not get block root for current epoch %d", prevEpoch) - } - return ðpb.Checkpoint{Epoch: currentEpoch, Root: blockRoot}, nil - } - if justification.BitAt(1) { - blockRoot, err := helpers.BlockRoot(st, prevEpoch) - if err != nil { - return nil, errors.Wrapf(err, "could not get block root for previous epoch %d", prevEpoch) - } - return ðpb.Checkpoint{Epoch: prevEpoch, Root: blockRoot}, nil - } - return st.CurrentJustifiedCheckpoint(), nil + return precompute.ComputeCheckpoints(st, justification) } diff --git a/beacon-chain/core/altair/epoch_precompute_test.go b/beacon-chain/core/altair/epoch_precompute_test.go index 7c4dbfd5b47f..ca93b90e4119 100644 --- a/beacon-chain/core/altair/epoch_precompute_test.go +++ b/beacon-chain/core/altair/epoch_precompute_test.go @@ -88,6 +88,16 @@ func TestInitializeEpochValidators_BadState(t *testing.T) { _, _, err = InitializePrecomputeValidators(context.Background(), s) require.ErrorContains(t, "num of validators is different than num of inactivity scores", err) } +func TestUnrealizedCheckpoints(t *testing.T) { + s, err := testState() + require.NoError(t, err) + _, _, err = InitializePrecomputeValidators(context.Background(), s) + require.NoError(t, err) + jc, fc, err := UnrealizedCheckpoints(context.Background(), s) + require.NoError(t, err) + require.Equal(t, 0, jc) + require.Equal(t, 0, fc) +} func TestProcessEpochParticipation(t *testing.T) { s, err := testState() diff --git a/beacon-chain/core/altair/error.go b/beacon-chain/core/altair/error.go new file mode 100644 index 000000000000..458b73b80336 --- /dev/null +++ b/beacon-chain/core/altair/error.go @@ -0,0 +1,5 @@ +package altair + +import "github.com/pkg/errors" + +var errNilState = errors.New("nil state") diff --git a/beacon-chain/core/epoch/precompute/justification_finalization.go b/beacon-chain/core/epoch/precompute/justification_finalization.go index 832dbdf16ac1..a6049c5c5e15 100644 --- a/beacon-chain/core/epoch/precompute/justification_finalization.go +++ b/beacon-chain/core/epoch/precompute/justification_finalization.go @@ -57,9 +57,34 @@ func ProcessJustificationBits(state state.BeaconState, totalActiveBalance, prevE return newBits } -// weighJustificationAndFinalization processes justification and finalization during +// 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.BeaconStateAltair, newBits bitfield.Bitvector4) (state.BeaconState, error) { + if err := state.SetPreviousJustifiedCheckpoint(state.CurrentJustifiedCheckpoint()); err != nil { + return nil, err + } + + jc, fc, err := ComputeCheckpoints(state, newBits) + if err != nil { + return nil, err + } + + if err := state.SetCurrentJustifiedCheckpoint(jc); err != nil { + return nil, err + } + + if err := state.SetJustificationBits(newBits); err != nil { + return nil, err + } + + if err := state.SetFinalizedCheckpoint(fc); err != nil { + return nil, err + } + return state, nil +} + +// ComputeCheckpoints computes the new Justification and Finalization +// checkpoints at epoch transition // Spec pseudocode definition: // def weigh_justification_and_finalization(state: BeaconState, // total_active_balance: Gwei, @@ -97,39 +122,31 @@ func ProcessJustificationBits(state state.BeaconState, totalActiveBalance, prevE // # 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 weighJustificationAndFinalization(state state.BeaconState, newBits bitfield.Bitvector4) (state.BeaconState, 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() oldCurrJustifiedCheckpoint := state.CurrentJustifiedCheckpoint() - // Process justifications - if err := state.SetPreviousJustifiedCheckpoint(state.CurrentJustifiedCheckpoint()); err != nil { - return nil, err - } + justifiedCheckpoint := ðpb.Checkpoint{} + finalizedCheckpoint := ðpb.Checkpoint{} // If 2/3 or more of the total balance attested in the current epoch. if newBits.BitAt(0) { blockRoot, err := helpers.BlockRoot(state, currentEpoch) if err != nil { - return nil, errors.Wrapf(err, "could not get block root for current epoch %d", prevEpoch) - } - if err := state.SetCurrentJustifiedCheckpoint(ðpb.Checkpoint{Epoch: currentEpoch, Root: blockRoot}); err != nil { - return nil, err + return nil, nil, errors.Wrapf(err, "could not get block root for current epoch %d", prevEpoch) } + justifiedCheckpoint.Epoch = currentEpoch + justifiedCheckpoint.Root = blockRoot } else if newBits.BitAt(1) { // If 2/3 or more of total balance attested in the previous epoch. blockRoot, err := helpers.BlockRoot(state, prevEpoch) if err != nil { - return nil, errors.Wrapf(err, "could not get block root for previous epoch %d", prevEpoch) + return nil, nil, errors.Wrapf(err, "could not get block root for previous epoch %d", prevEpoch) } - if err := state.SetCurrentJustifiedCheckpoint(ðpb.Checkpoint{Epoch: prevEpoch, Root: blockRoot}); err != nil { - return nil, err - } - } - - if err := state.SetJustificationBits(newBits); err != nil { - return nil, err + justifiedCheckpoint.Epoch = prevEpoch + justifiedCheckpoint.Root = blockRoot } // Process finalization according to Ethereum Beacon Chain specification. @@ -137,31 +154,22 @@ func weighJustificationAndFinalization(state state.BeaconState, newBits bitfield // 2nd/3rd/4th (0b1110) most recent epochs are justified, the 2nd using the 4th as source. if justification&0x0E == 0x0E && (oldPrevJustifiedCheckpoint.Epoch+3) == currentEpoch { - if err := state.SetFinalizedCheckpoint(oldPrevJustifiedCheckpoint); err != nil { - return nil, err - } + finalizedCheckpoint = oldPrevJustifiedCheckpoint } // 2nd/3rd (0b0110) most recent epochs are justified, the 2nd using the 3rd as source. if justification&0x06 == 0x06 && (oldPrevJustifiedCheckpoint.Epoch+2) == currentEpoch { - if err := state.SetFinalizedCheckpoint(oldPrevJustifiedCheckpoint); err != nil { - return nil, err - } + finalizedCheckpoint = oldPrevJustifiedCheckpoint } // 1st/2nd/3rd (0b0111) most recent epochs are justified, the 1st using the 3rd as source. if justification&0x07 == 0x07 && (oldCurrJustifiedCheckpoint.Epoch+2) == currentEpoch { - if err := state.SetFinalizedCheckpoint(oldCurrJustifiedCheckpoint); err != nil { - return nil, err - } + finalizedCheckpoint = oldCurrJustifiedCheckpoint } // The 1st/2nd (0b0011) most recent epochs are justified, the 1st using the 2nd as source if justification&0x03 == 0x03 && (oldCurrJustifiedCheckpoint.Epoch+1) == currentEpoch { - if err := state.SetFinalizedCheckpoint(oldCurrJustifiedCheckpoint); err != nil { - return nil, err - } + finalizedCheckpoint = oldCurrJustifiedCheckpoint } - - return state, nil + return justifiedCheckpoint, finalizedCheckpoint, nil } From ac56101de239c275581b752c3681236447d3f2c8 Mon Sep 17 00:00:00 2001 From: Potuz Date: Thu, 19 May 2022 17:45:16 -0300 Subject: [PATCH 06/28] Move logic to state package --- beacon-chain/core/altair/epoch_precompute.go | 46 +--------------- beacon-chain/state/phase0.go | 1 + beacon-chain/state/state-native/BUILD.bazel | 3 ++ beacon-chain/state/state-native/error.go | 5 ++ .../state-native/getters_participation.go | 47 ++++++++++++++++ beacon-chain/state/v1/unsupported_getters.go | 5 ++ beacon-chain/state/v2/BUILD.bazel | 3 ++ beacon-chain/state/v2/error.go | 5 ++ .../state/v2/getters_participation.go | 53 +++++++++++++++++++ beacon-chain/state/v3/BUILD.bazel | 3 ++ beacon-chain/state/v3/error.go | 5 ++ .../state/v3/getters_participation.go | 53 +++++++++++++++++++ 12 files changed, 184 insertions(+), 45 deletions(-) create mode 100644 beacon-chain/state/state-native/error.go create mode 100644 beacon-chain/state/v2/error.go create mode 100644 beacon-chain/state/v3/error.go diff --git a/beacon-chain/core/altair/epoch_precompute.go b/beacon-chain/core/altair/epoch_precompute.go index eae04477a40f..6986f870f1ec 100644 --- a/beacon-chain/core/altair/epoch_precompute.go +++ b/beacon-chain/core/altair/epoch_precompute.go @@ -359,56 +359,12 @@ func UnrealizedCheckpoints(ctx context.Context, st state.BeaconStateAltair) (*et if st == nil || st.IsNil() { return nil, nil, errNilState } - currentEpoch := time.CurrentEpoch(st) - activeBalance := uint64(0) - currentTarget := uint64(0) - prevTarget := uint64(0) - cp, err := st.CurrentEpochParticipation() // TODO: Use read only + activeBalance, prevTarget, currentTarget, err := st.UnrealizedCheckpointBalances() if err != nil { return nil, nil, err } - pp, err := st.PreviousEpochParticipation() - if err != nil { - return nil, nil, err - } - - cfg := params.BeaconConfig() - targetIdx := cfg.TimelyTargetFlagIndex - - if err := st.ReadFromEveryValidator(func(idx int, val state.ReadOnlyValidator) error { - if helpers.IsActiveValidatorUsingTrie(val, currentEpoch) && !val.Slashed() { - activeBalance, err = math.Add64(activeBalance, val.EffectiveBalance()) - if err != nil { - return err - } - has, err := HasValidatorFlag(cp[idx], targetIdx) - if err != nil { - return err - } - if has { - currentTarget, err = math.Add64(currentTarget, val.EffectiveBalance()) - if err != nil { - return err - } - } - has, err = HasValidatorFlag(pp[idx], targetIdx) - if err != nil { - return err - } - if has { - prevTarget, err = math.Add64(prevTarget, val.EffectiveBalance()) - if err != nil { - return err - } - } - } - return nil - }); err != nil { - return nil, nil, errors.Wrap(err, "could not read every validator") - } - justification := precompute.ProcessJustificationBits(st, activeBalance, prevTarget, currentTarget) return precompute.ComputeCheckpoints(st, justification) } diff --git a/beacon-chain/state/phase0.go b/beacon-chain/state/phase0.go index 6171be4ff35b..009b72326434 100644 --- a/beacon-chain/state/phase0.go +++ b/beacon-chain/state/phase0.go @@ -215,6 +215,7 @@ type FutureForkStub interface { AppendInactivityScore(s uint64) error CurrentEpochParticipation() ([]byte, error) PreviousEpochParticipation() ([]byte, error) + UnrealizedCheckpointBalances() (uint64, uint64, uint64, error) InactivityScores() ([]uint64, error) SetInactivityScores(val []uint64) error CurrentSyncCommittee() (*ethpb.SyncCommittee, error) diff --git a/beacon-chain/state/state-native/BUILD.bazel b/beacon-chain/state/state-native/BUILD.bazel index 0b2f870ca37f..3a6ff682469b 100644 --- a/beacon-chain/state/state-native/BUILD.bazel +++ b/beacon-chain/state/state-native/BUILD.bazel @@ -4,6 +4,7 @@ go_library( name = "go_default_library", srcs = [ "doc.go", + "error.go", "getters_attestation.go", "getters_block.go", "getters_checkpoint.go", @@ -53,6 +54,7 @@ go_library( "//tools/pcli:__pkg__", ], deps = [ + "//beacon-chain/core/time:go_default_library", "//beacon-chain/state:go_default_library", "//beacon-chain/state/fieldtrie:go_default_library", "//beacon-chain/state/state-native/custom-types:go_default_library", @@ -66,6 +68,7 @@ go_library( "//crypto/hash:go_default_library", "//encoding/bytesutil:go_default_library", "//encoding/ssz:go_default_library", + "//math:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//runtime/version:go_default_library", "@com_github_ferranbt_fastssz//:go_default_library", diff --git a/beacon-chain/state/state-native/error.go b/beacon-chain/state/state-native/error.go new file mode 100644 index 000000000000..ac8dde525ec5 --- /dev/null +++ b/beacon-chain/state/state-native/error.go @@ -0,0 +1,5 @@ +package state_native + +import "errors" + +var ErrNilParticipation = errors.New("Nil epoch participation in state") diff --git a/beacon-chain/state/state-native/getters_participation.go b/beacon-chain/state/state-native/getters_participation.go index c81a97028576..52db5696d59a 100644 --- a/beacon-chain/state/state-native/getters_participation.go +++ b/beacon-chain/state/state-native/getters_participation.go @@ -1,6 +1,9 @@ package state_native import ( + "github.com/prysmaticlabs/prysm/beacon-chain/core/time" + "github.com/prysmaticlabs/prysm/config/params" + "github.com/prysmaticlabs/prysm/math" "github.com/prysmaticlabs/prysm/runtime/version" ) @@ -36,6 +39,50 @@ func (b *BeaconState) PreviousEpochParticipation() ([]byte, error) { return b.previousEpochParticipationVal(), nil } +// UnrealizedCheckpointBalances returns the total balances: active, target attested in +// current epoch and target attested in previous epoch. This function is used to +// compute the "unrealized justification" that a synced Beacon Block will have. +func (b *BeaconState) UnrealizedCheckpointBalances() (uint64, uint64, uint64, error) { + b.lock.RLock() + defer b.lock.RUnlock() + + cp := b.currentEpochParticipation + pp := b.previousEpochParticipation + if cp == nil || pp == nil { + return 0, 0, 0, ErrNilParticipation + } + + targetIdx := params.BeaconConfig().TimelyTargetFlagIndex + activeBalance := uint64(0) + currentTarget := uint64(0) + prevTarget := uint64(0) + currentEpoch := time.CurrentEpoch(b) + + var err error + for i, v := range b.validators { + active := v.ActivationEpoch <= currentEpoch && currentEpoch < v.ExitEpoch + if active && !v.Slashed { + activeBalance, err = math.Add64(activeBalance, v.EffectiveBalance) + if err != nil { + return 0, 0, 0, err + } + if ((cp[i] >> targetIdx) & 1) == 1 { + currentTarget, err = math.Add64(currentTarget, v.EffectiveBalance) + if err != nil { + return 0, 0, 0, err + } + } + if ((pp[i] >> targetIdx) & 1) == 1 { + prevTarget, err = math.Add64(prevTarget, v.EffectiveBalance) + if err != nil { + return 0, 0, 0, err + } + } + } + } + return activeBalance, prevTarget, currentTarget, nil +} + // currentEpochParticipationVal corresponding to participation bits on the beacon chain. // This assumes that a lock is already held on BeaconState. func (b *BeaconState) currentEpochParticipationVal() []byte { diff --git a/beacon-chain/state/v1/unsupported_getters.go b/beacon-chain/state/v1/unsupported_getters.go index 3717aab456f5..010807f4c732 100644 --- a/beacon-chain/state/v1/unsupported_getters.go +++ b/beacon-chain/state/v1/unsupported_getters.go @@ -15,6 +15,11 @@ func (*BeaconState) PreviousEpochParticipation() ([]byte, error) { return nil, errors.New("PreviousEpochParticipation is not supported for phase 0 beacon state") } +// UnrealizedCheckpointBalances is not supported for phase 0 beacon state. +func (*BeaconState) UnrealizedCheckpointBalances() (uint64, uint64, uint64, error) { + return 0, 0, 0, errors.New("UnrealizedCheckpointBalances is not supported for phase0 beacon state") +} + // InactivityScores is not supported for phase 0 beacon state. func (*BeaconState) InactivityScores() ([]uint64, error) { return nil, errors.New("InactivityScores is not supported for phase 0 beacon state") diff --git a/beacon-chain/state/v2/BUILD.bazel b/beacon-chain/state/v2/BUILD.bazel index 0e51337f311f..73d705c45b42 100644 --- a/beacon-chain/state/v2/BUILD.bazel +++ b/beacon-chain/state/v2/BUILD.bazel @@ -5,6 +5,7 @@ go_library( srcs = [ "deprecated_getters.go", "deprecated_setters.go", + "error.go", "field_roots.go", "getters_block.go", "getters_checkpoint.go", @@ -31,6 +32,7 @@ go_library( importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state/v2", visibility = ["//visibility:public"], deps = [ + "//beacon-chain/core/time:go_default_library", "//beacon-chain/state:go_default_library", "//beacon-chain/state/fieldtrie:go_default_library", "//beacon-chain/state/state-native:go_default_library", @@ -45,6 +47,7 @@ go_library( "//crypto/hash:go_default_library", "//encoding/bytesutil:go_default_library", "//encoding/ssz:go_default_library", + "//math:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//runtime/version:go_default_library", "@com_github_pkg_errors//:go_default_library", diff --git a/beacon-chain/state/v2/error.go b/beacon-chain/state/v2/error.go new file mode 100644 index 000000000000..7ab7be4dc668 --- /dev/null +++ b/beacon-chain/state/v2/error.go @@ -0,0 +1,5 @@ +package v2 + +import "errors" + +var ErrNilParticipation = errors.New("Nil epoch participation in state") diff --git a/beacon-chain/state/v2/getters_participation.go b/beacon-chain/state/v2/getters_participation.go index 6c90e12cb78a..1e6c8bcdc237 100644 --- a/beacon-chain/state/v2/getters_participation.go +++ b/beacon-chain/state/v2/getters_participation.go @@ -1,5 +1,11 @@ package v2 +import ( + "github.com/prysmaticlabs/prysm/beacon-chain/core/time" + "github.com/prysmaticlabs/prysm/config/params" + "github.com/prysmaticlabs/prysm/math" +) + // CurrentEpochParticipation corresponding to participation bits on the beacon chain. func (b *BeaconState) CurrentEpochParticipation() ([]byte, error) { if !b.hasInnerState() { @@ -30,6 +36,53 @@ func (b *BeaconState) PreviousEpochParticipation() ([]byte, error) { return b.previousEpochParticipation(), nil } +// UnrealizedCheckpointBalances returns the total balances: active, target attested in +// current epoch and target attested in previous epoch. This function is used to +// compute the "unrealized justification" that a synced Beacon Block will have. +func (b *BeaconState) UnrealizedCheckpointBalances() (uint64, uint64, uint64, error) { + if !b.hasInnerState() { + return 0, 0, 0, ErrNilInnerState + } + b.lock.RLock() + defer b.lock.RUnlock() + + cp := b.state.CurrentEpochParticipation + pp := b.state.PreviousEpochParticipation + if cp == nil || pp == nil { + return 0, 0, 0, ErrNilParticipation + } + + targetIdx := params.BeaconConfig().TimelyTargetFlagIndex + activeBalance := uint64(0) + currentTarget := uint64(0) + prevTarget := uint64(0) + currentEpoch := time.CurrentEpoch(b) + + var err error + for i, v := range b.state.Validators { + active := v.ActivationEpoch <= currentEpoch && currentEpoch < v.ExitEpoch + if active && !v.Slashed { + activeBalance, err = math.Add64(activeBalance, v.EffectiveBalance) + if err != nil { + return 0, 0, 0, err + } + if ((cp[i] >> targetIdx) & 1) == 1 { + currentTarget, err = math.Add64(currentTarget, v.EffectiveBalance) + if err != nil { + return 0, 0, 0, err + } + } + if ((pp[i] >> targetIdx) & 1) == 1 { + prevTarget, err = math.Add64(prevTarget, v.EffectiveBalance) + if err != nil { + return 0, 0, 0, err + } + } + } + } + return activeBalance, prevTarget, currentTarget, nil +} + // currentEpochParticipation corresponding to participation bits on the beacon chain. // This assumes that a lock is already held on BeaconState. func (b *BeaconState) currentEpochParticipation() []byte { diff --git a/beacon-chain/state/v3/BUILD.bazel b/beacon-chain/state/v3/BUILD.bazel index edcff6926070..d1c727dff857 100644 --- a/beacon-chain/state/v3/BUILD.bazel +++ b/beacon-chain/state/v3/BUILD.bazel @@ -5,6 +5,7 @@ go_library( srcs = [ "deprecated_getters.go", "deprecated_setters.go", + "error.go", "field_roots.go", "getters_block.go", "getters_checkpoint.go", @@ -33,6 +34,7 @@ go_library( importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state/v3", visibility = ["//visibility:public"], deps = [ + "//beacon-chain/core/time:go_default_library", "//beacon-chain/state:go_default_library", "//beacon-chain/state/fieldtrie:go_default_library", "//beacon-chain/state/state-native:go_default_library", @@ -47,6 +49,7 @@ go_library( "//crypto/hash:go_default_library", "//encoding/bytesutil:go_default_library", "//encoding/ssz:go_default_library", + "//math:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//runtime/version:go_default_library", "@com_github_pkg_errors//:go_default_library", diff --git a/beacon-chain/state/v3/error.go b/beacon-chain/state/v3/error.go new file mode 100644 index 000000000000..f7773f8a6db3 --- /dev/null +++ b/beacon-chain/state/v3/error.go @@ -0,0 +1,5 @@ +package v3 + +import "errors" + +var ErrNilParticipation = errors.New("Nil epoch participation in state") diff --git a/beacon-chain/state/v3/getters_participation.go b/beacon-chain/state/v3/getters_participation.go index 48acdbde53e8..a4c9261f78cc 100644 --- a/beacon-chain/state/v3/getters_participation.go +++ b/beacon-chain/state/v3/getters_participation.go @@ -1,5 +1,11 @@ package v3 +import ( + "github.com/prysmaticlabs/prysm/beacon-chain/core/time" + "github.com/prysmaticlabs/prysm/config/params" + "github.com/prysmaticlabs/prysm/math" +) + // CurrentEpochParticipation corresponding to participation bits on the beacon chain. func (b *BeaconState) CurrentEpochParticipation() ([]byte, error) { if !b.hasInnerState() { @@ -30,6 +36,53 @@ func (b *BeaconState) PreviousEpochParticipation() ([]byte, error) { return b.previousEpochParticipation(), nil } +// UnrealizedCheckpointBalances returns the total balances: active, target attested in +// current epoch and target attested in previous epoch. This function is used to +// compute the "unrealized justification" that a synced Beacon Block will have. +func (b *BeaconState) UnrealizedCheckpointBalances() (uint64, uint64, uint64, error) { + if !b.hasInnerState() { + return 0, 0, 0, ErrNilInnerState + } + b.lock.RLock() + defer b.lock.RUnlock() + + cp := b.state.CurrentEpochParticipation + pp := b.state.PreviousEpochParticipation + if cp == nil || pp == nil { + return 0, 0, 0, ErrNilParticipation + } + + targetIdx := params.BeaconConfig().TimelyTargetFlagIndex + activeBalance := uint64(0) + currentTarget := uint64(0) + prevTarget := uint64(0) + currentEpoch := time.CurrentEpoch(b) + + var err error + for i, v := range b.state.Validators { + active := v.ActivationEpoch <= currentEpoch && currentEpoch < v.ExitEpoch + if active && !v.Slashed { + activeBalance, err = math.Add64(activeBalance, v.EffectiveBalance) + if err != nil { + return 0, 0, 0, err + } + if ((cp[i] >> targetIdx) & 1) == 1 { + currentTarget, err = math.Add64(currentTarget, v.EffectiveBalance) + if err != nil { + return 0, 0, 0, err + } + } + if ((pp[i] >> targetIdx) & 1) == 1 { + prevTarget, err = math.Add64(prevTarget, v.EffectiveBalance) + if err != nil { + return 0, 0, 0, err + } + } + } + } + return activeBalance, prevTarget, currentTarget, nil +} + // currentEpochParticipation corresponding to participation bits on the beacon chain. // This assumes that a lock is already held on BeaconState. func (b *BeaconState) currentEpochParticipation() []byte { From 03e36aee3537b812f586258729703dcd94324b72 Mon Sep 17 00:00:00 2001 From: Potuz Date: Thu, 19 May 2022 17:48:56 -0300 Subject: [PATCH 07/28] do not use ctx on a sum --- beacon-chain/core/altair/epoch_precompute.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beacon-chain/core/altair/epoch_precompute.go b/beacon-chain/core/altair/epoch_precompute.go index 6986f870f1ec..7897024f096a 100644 --- a/beacon-chain/core/altair/epoch_precompute.go +++ b/beacon-chain/core/altair/epoch_precompute.go @@ -355,7 +355,7 @@ func attestationDelta( // UnrealizedCheckpoints returns the justification and finalization checkpoints of the // given state as if it was progressed with empty slots until the next epoch. -func UnrealizedCheckpoints(ctx context.Context, st state.BeaconStateAltair) (*ethpb.Checkpoint, *ethpb.Checkpoint, error) { +func UnrealizedCheckpoints(st state.BeaconStateAltair) (*ethpb.Checkpoint, *ethpb.Checkpoint, error) { if st == nil || st.IsNil() { return nil, nil, errNilState } From a818433934d294b60273e67a26ebcc07a1a0ae8d Mon Sep 17 00:00:00 2001 From: Potuz Date: Thu, 19 May 2022 17:55:01 -0300 Subject: [PATCH 08/28] fix ctx --- beacon-chain/core/altair/epoch_precompute_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/beacon-chain/core/altair/epoch_precompute_test.go b/beacon-chain/core/altair/epoch_precompute_test.go index ca93b90e4119..eda35495236c 100644 --- a/beacon-chain/core/altair/epoch_precompute_test.go +++ b/beacon-chain/core/altair/epoch_precompute_test.go @@ -88,12 +88,13 @@ func TestInitializeEpochValidators_BadState(t *testing.T) { _, _, err = InitializePrecomputeValidators(context.Background(), s) require.ErrorContains(t, "num of validators is different than num of inactivity scores", err) } + func TestUnrealizedCheckpoints(t *testing.T) { s, err := testState() require.NoError(t, err) _, _, err = InitializePrecomputeValidators(context.Background(), s) require.NoError(t, err) - jc, fc, err := UnrealizedCheckpoints(context.Background(), s) + jc, fc, err := UnrealizedCheckpoints(s) require.NoError(t, err) require.Equal(t, 0, jc) require.Equal(t, 0, fc) From fc15febb2216db1c8450ac9353f2aea08be5ce93 Mon Sep 17 00:00:00 2001 From: Potuz Date: Thu, 19 May 2022 18:19:01 -0300 Subject: [PATCH 09/28] add tests --- beacon-chain/state/v1/getters_test.go | 1 + beacon-chain/state/v2/getters_test.go | 2 ++ beacon-chain/state/v3/getters_test.go | 2 ++ 3 files changed, 5 insertions(+) diff --git a/beacon-chain/state/v1/getters_test.go b/beacon-chain/state/v1/getters_test.go index 474dbc503f7e..9b1bdc1dc7be 100644 --- a/beacon-chain/state/v1/getters_test.go +++ b/beacon-chain/state/v1/getters_test.go @@ -63,6 +63,7 @@ func TestNilState_NoPanic(t *testing.T) { _ = st.PreviousJustifiedCheckpoint() _ = st.CurrentJustifiedCheckpoint() _ = st.FinalizedCheckpoint() + _, _, _, _ = st.UnrealizedCheckpointBalances() } func TestBeaconState_MatchCurrentJustifiedCheckpt(t *testing.T) { diff --git a/beacon-chain/state/v2/getters_test.go b/beacon-chain/state/v2/getters_test.go index 8ccff4e626e5..d116415279d7 100644 --- a/beacon-chain/state/v2/getters_test.go +++ b/beacon-chain/state/v2/getters_test.go @@ -74,6 +74,8 @@ func TestNilState_NoPanic(t *testing.T) { require.ErrorIs(t, ErrNilInnerState, err) _, err = st.NextSyncCommittee() require.ErrorIs(t, ErrNilInnerState, err) + _, _, _, err = st.UnrealizedCheckpointBalances() + require.ErrorIs(t, ErrNilInnerState, err) } func TestBeaconState_MatchCurrentJustifiedCheckpt(t *testing.T) { diff --git a/beacon-chain/state/v3/getters_test.go b/beacon-chain/state/v3/getters_test.go index 58928b423802..f84cec720023 100644 --- a/beacon-chain/state/v3/getters_test.go +++ b/beacon-chain/state/v3/getters_test.go @@ -75,6 +75,8 @@ func TestNilState_NoPanic(t *testing.T) { require.ErrorIs(t, ErrNilInnerState, err) _, err = st.LatestExecutionPayloadHeader() require.ErrorIs(t, ErrNilInnerState, err) + _, _, _, err = st.UnrealizedCheckpointBalances() + require.ErrorIs(t, ErrNilInnerState, err) } From 3457e984248f2cff617446b7b238171624ddbf47 Mon Sep 17 00:00:00 2001 From: Potuz Date: Sat, 21 May 2022 09:31:05 -0300 Subject: [PATCH 10/28] fix conflicts --- beacon-chain/core/altair/epoch_precompute.go | 2 +- .../core/epoch/precompute/justification_finalization.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/beacon-chain/core/altair/epoch_precompute.go b/beacon-chain/core/altair/epoch_precompute.go index d516f691b412..3d80aa5a2d69 100644 --- a/beacon-chain/core/altair/epoch_precompute.go +++ b/beacon-chain/core/altair/epoch_precompute.go @@ -350,7 +350,7 @@ func attestationDelta( // UnrealizedCheckpoints returns the justification and finalization checkpoints of the // given state as if it was progressed with empty slots until the next epoch. -func UnrealizedCheckpoints(st state.BeaconStateAltair) (*ethpb.Checkpoint, *ethpb.Checkpoint, error) { +func UnrealizedCheckpoints(st state.BeaconState) (*ethpb.Checkpoint, *ethpb.Checkpoint, error) { if st == nil || st.IsNil() { return nil, nil, errNilState } diff --git a/beacon-chain/core/epoch/precompute/justification_finalization.go b/beacon-chain/core/epoch/precompute/justification_finalization.go index 08faf0f527c3..a5f546d96650 100644 --- a/beacon-chain/core/epoch/precompute/justification_finalization.go +++ b/beacon-chain/core/epoch/precompute/justification_finalization.go @@ -59,7 +59,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.BeaconStateAltair, newBits bitfield.Bitvector4) (state.BeaconState, error) { +func weighJustificationAndFinalization(state state.BeaconState, newBits bitfield.Bitvector4) (state.BeaconState, error) { if err := state.SetPreviousJustifiedCheckpoint(state.CurrentJustifiedCheckpoint()); err != nil { return nil, err } From 05682fdd991d0ec29ced078e6df84ec87f8d56a7 Mon Sep 17 00:00:00 2001 From: Potuz Date: Sat, 21 May 2022 10:37:38 -0300 Subject: [PATCH 11/28] unhandled error --- beacon-chain/state/v1/getters_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/beacon-chain/state/v1/getters_test.go b/beacon-chain/state/v1/getters_test.go index 9b1bdc1dc7be..c2bd2138c118 100644 --- a/beacon-chain/state/v1/getters_test.go +++ b/beacon-chain/state/v1/getters_test.go @@ -63,7 +63,8 @@ func TestNilState_NoPanic(t *testing.T) { _ = st.PreviousJustifiedCheckpoint() _ = st.CurrentJustifiedCheckpoint() _ = st.FinalizedCheckpoint() - _, _, _, _ = st.UnrealizedCheckpointBalances() + _, _, _, err = st.UnrealizedCheckpointBalances() + _ = err } func TestBeaconState_MatchCurrentJustifiedCheckpt(t *testing.T) { From 62a7863db1d91d2edcbb1bddf99367accbdabda5 Mon Sep 17 00:00:00 2001 From: Potuz Date: Sun, 22 May 2022 10:38:26 -0300 Subject: [PATCH 12/28] Fix ordering in computing checkpoints --- .../precompute/justification_finalization.go | 11 +- .../justification_finalization.go.orig | 216 ------------------ .../shared/altair/finality/BUILD.bazel | 1 + 3 files changed, 7 insertions(+), 221 deletions(-) delete mode 100644 beacon-chain/core/epoch/precompute/justification_finalization.go.orig diff --git a/beacon-chain/core/epoch/precompute/justification_finalization.go b/beacon-chain/core/epoch/precompute/justification_finalization.go index a5f546d96650..018fdfc74c9b 100644 --- a/beacon-chain/core/epoch/precompute/justification_finalization.go +++ b/beacon-chain/core/epoch/precompute/justification_finalization.go @@ -60,12 +60,12 @@ 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) { - if err := state.SetPreviousJustifiedCheckpoint(state.CurrentJustifiedCheckpoint()); err != nil { + jc, fc, err := ComputeCheckpoints(state, newBits) + if err != nil { return nil, err } - jc, fc, err := ComputeCheckpoints(state, newBits) - if err != nil { + if err := state.SetPreviousJustifiedCheckpoint(state.CurrentJustifiedCheckpoint()); err != nil { return nil, err } @@ -135,7 +135,7 @@ func ComputeCheckpoints(state state.BeaconState, newBits bitfield.Bitvector4) (* if newBits.BitAt(0) { blockRoot, err := helpers.BlockRoot(state, currentEpoch) if err != nil { - return nil, nil, errors.Wrapf(err, "could not get block root for current epoch %d", prevEpoch) + return nil, nil, errors.Wrapf(err, "could not get block root for current epoch %d", currentEpoch) } justifiedCheckpoint.Epoch = currentEpoch justifiedCheckpoint.Root = blockRoot @@ -151,7 +151,8 @@ func ComputeCheckpoints(state state.BeaconState, newBits bitfield.Bitvector4) (* // Process finalization according to Ethereum Beacon Chain specification. if len(newBits) == 0 { - return justifiedCheckpoint, finalizedCheckpoint, nil + finalizedCheckpoint = state.FinalizedCheckpoint() + return oldCurrJustifiedCheckpoint, finalizedCheckpoint, nil } justification := newBits.Bytes()[0] diff --git a/beacon-chain/core/epoch/precompute/justification_finalization.go.orig b/beacon-chain/core/epoch/precompute/justification_finalization.go.orig deleted file mode 100644 index 8b01d4b8d322..000000000000 --- a/beacon-chain/core/epoch/precompute/justification_finalization.go.orig +++ /dev/null @@ -1,216 +0,0 @@ -package precompute - -import ( - "github.com/pkg/errors" - "github.com/prysmaticlabs/go-bitfield" - "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" - "github.com/prysmaticlabs/prysm/beacon-chain/core/time" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/time/slots" -) - -// ProcessJustificationAndFinalizationPreCompute processes justification and finalization during -// epoch processing. This is where a beacon node can justify and finalize a new epoch. -// Note: this is an optimized version by passing in precomputed total and attesting balances. -// -// Spec pseudocode definition: -// def process_justification_and_finalization(state: BeaconState) -> None: -// # Initial FFG checkpoint values have a `0x00` stub for `root`. -// # Skip FFG updates in the first two epochs to avoid corner cases that might result in modifying this stub. -// if get_current_epoch(state) <= GENESIS_EPOCH + 1: -// return -// previous_attestations = get_matching_target_attestations(state, get_previous_epoch(state)) -// current_attestations = get_matching_target_attestations(state, get_current_epoch(state)) -// total_active_balance = get_total_active_balance(state) -// previous_target_balance = get_attesting_balance(state, previous_attestations) -// current_target_balance = get_attesting_balance(state, current_attestations) -// weigh_justification_and_finalization(state, total_active_balance, previous_target_balance, current_target_balance) -func ProcessJustificationAndFinalizationPreCompute(state state.BeaconState, pBal *Balance) (state.BeaconState, error) { - canProcessSlot, err := slots.EpochStart(2 /*epoch*/) - if err != nil { - return nil, err - } - if state.Slot() <= canProcessSlot { - return state, nil - } - - newBits := ProcessJustificationBits(state, pBal.ActiveCurrentEpoch, pBal.PrevEpochTargetAttested, pBal.CurrentEpochTargetAttested) - - return weighJustificationAndFinalization(state, newBits) -} - -// ProcessJustificationBits processes the justification bits during epoch -// processing. -func ProcessJustificationBits(state state.BeaconState, totalActiveBalance, prevEpochTargetBalance, currEpochTargetBalance uint64) bitfield.Bitvector4 { - newBits := state.JustificationBits() - newBits.Shift(1) - // If 2/3 or more of total balance attested in the previous epoch. - if 3*prevEpochTargetBalance >= 2*totalActiveBalance { - newBits.SetBitAt(1, true) - } - - if 3*currEpochTargetBalance >= 2*totalActiveBalance { - newBits.SetBitAt(0, true) - } - - return newBits -} - -// 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.BeaconStateAltair, newBits bitfield.Bitvector4) (state.BeaconState, error) { - if err := state.SetPreviousJustifiedCheckpoint(state.CurrentJustifiedCheckpoint()); err != nil { - return nil, err - } - - jc, fc, err := ComputeCheckpoints(state, newBits) - if err != nil { - return nil, err - } - - if err := state.SetCurrentJustifiedCheckpoint(jc); err != nil { - return nil, err - } - - if err := state.SetJustificationBits(newBits); err != nil { - return nil, err - } - - if err := state.SetFinalizedCheckpoint(fc); err != nil { - return nil, err - } - return state, nil -} - -// ComputeCheckpoints computes the new Justification and Finalization -// checkpoints at epoch transition -// Spec pseudocode definition: -// def weigh_justification_and_finalization(state: BeaconState, -// total_active_balance: Gwei, -// previous_epoch_target_balance: Gwei, -// current_epoch_target_balance: Gwei) -> None: -// previous_epoch = get_previous_epoch(state) -// current_epoch = get_current_epoch(state) -// old_previous_justified_checkpoint = state.previous_justified_checkpoint -// old_current_justified_checkpoint = state.current_justified_checkpoint -// -// # Process justifications -// state.previous_justified_checkpoint = state.current_justified_checkpoint -// state.justification_bits[1:] = state.justification_bits[:JUSTIFICATION_BITS_LENGTH - 1] -// state.justification_bits[0] = 0b0 -// if previous_epoch_target_balance * 3 >= total_active_balance * 2: -// state.current_justified_checkpoint = Checkpoint(epoch=previous_epoch, -// root=get_block_root(state, previous_epoch)) -// state.justification_bits[1] = 0b1 -// if current_epoch_target_balance * 3 >= total_active_balance * 2: -// state.current_justified_checkpoint = Checkpoint(epoch=current_epoch, -// root=get_block_root(state, current_epoch)) -// state.justification_bits[0] = 0b1 -// -// # Process finalizations -// bits = state.justification_bits -// # The 2nd/3rd/4th most recent epochs are justified, the 2nd using the 4th as source -// if all(bits[1:4]) and old_previous_justified_checkpoint.epoch + 3 == current_epoch: -// state.finalized_checkpoint = old_previous_justified_checkpoint -// # The 2nd/3rd most recent epochs are justified, the 2nd using the 3rd as source -// if all(bits[1:3]) and old_previous_justified_checkpoint.epoch + 2 == current_epoch: -// state.finalized_checkpoint = old_previous_justified_checkpoint -// # The 1st/2nd/3rd most recent epochs are justified, the 1st using the 3rd as source -// if all(bits[0:3]) and old_current_justified_checkpoint.epoch + 2 == current_epoch: -// state.finalized_checkpoint = old_current_justified_checkpoint -// # 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) { - prevEpoch := time.PrevEpoch(state) - currentEpoch := time.CurrentEpoch(state) - oldPrevJustifiedCheckpoint := state.PreviousJustifiedCheckpoint() - oldCurrJustifiedCheckpoint := state.CurrentJustifiedCheckpoint() - -<<<<<<< HEAD - justifiedCheckpoint := ðpb.Checkpoint{} - finalizedCheckpoint := ðpb.Checkpoint{} -======= - // Process justifications - if err := state.SetPreviousJustifiedCheckpoint(state.CurrentJustifiedCheckpoint()); err != nil { - return nil, err - } - newBits := state.JustificationBits() - newBits.Shift(1) - if err := state.SetJustificationBits(newBits); err != nil { - return nil, err - } - - // Note: the spec refers to the bit index position starting at 1 instead of starting at zero. - // We will use that paradigm here for consistency with the godoc spec definition. - - // If 2/3 or more of total balance attested in the previous epoch. - if 3*prevEpochTargetBalance >= 2*totalActiveBalance { - blockRoot, err := helpers.BlockRoot(state, prevEpoch) - if err != nil { - return nil, errors.Wrapf(err, "could not get block root for previous epoch %d", prevEpoch) - } - if err := state.SetCurrentJustifiedCheckpoint(ðpb.Checkpoint{Epoch: prevEpoch, Root: blockRoot}); err != nil { - return nil, err - } - newBits = state.JustificationBits() - newBits.SetBitAt(1, true) - if err := state.SetJustificationBits(newBits); err != nil { - return nil, err - } - } ->>>>>>> develop - - // If 2/3 or more of the total balance attested in the current epoch. - if newBits.BitAt(0) { - blockRoot, err := helpers.BlockRoot(state, currentEpoch) - if err != nil { - return nil, nil, errors.Wrapf(err, "could not get block root for current epoch %d", prevEpoch) - } -<<<<<<< HEAD - justifiedCheckpoint.Epoch = currentEpoch - justifiedCheckpoint.Root = blockRoot - } else if newBits.BitAt(1) { - // If 2/3 or more of total balance attested in the previous epoch. - blockRoot, err := helpers.BlockRoot(state, prevEpoch) - if err != nil { - return nil, nil, errors.Wrapf(err, "could not get block root for previous epoch %d", prevEpoch) -======= - if err := state.SetCurrentJustifiedCheckpoint(ðpb.Checkpoint{Epoch: currentEpoch, Root: blockRoot}); err != nil { - return nil, err - } - newBits = state.JustificationBits() - newBits.SetBitAt(0, true) - if err := state.SetJustificationBits(newBits); err != nil { - return nil, err ->>>>>>> develop - } - justifiedCheckpoint.Epoch = prevEpoch - justifiedCheckpoint.Root = blockRoot - } - - // Process finalization according to Ethereum Beacon Chain specification. - justification := newBits.Bytes()[0] - - // 2nd/3rd/4th (0b1110) most recent epochs are justified, the 2nd using the 4th as source. - if justification&0x0E == 0x0E && (oldPrevJustifiedCheckpoint.Epoch+3) == currentEpoch { - finalizedCheckpoint = oldPrevJustifiedCheckpoint - } - - // 2nd/3rd (0b0110) most recent epochs are justified, the 2nd using the 3rd as source. - if justification&0x06 == 0x06 && (oldPrevJustifiedCheckpoint.Epoch+2) == currentEpoch { - finalizedCheckpoint = oldPrevJustifiedCheckpoint - } - - // 1st/2nd/3rd (0b0111) most recent epochs are justified, the 1st using the 3rd as source. - if justification&0x07 == 0x07 && (oldCurrJustifiedCheckpoint.Epoch+2) == currentEpoch { - finalizedCheckpoint = oldCurrJustifiedCheckpoint - } - - // The 1st/2nd (0b0011) most recent epochs are justified, the 1st using the 2nd as source - if justification&0x03 == 0x03 && (oldCurrJustifiedCheckpoint.Epoch+1) == currentEpoch { - finalizedCheckpoint = oldCurrJustifiedCheckpoint - } - return justifiedCheckpoint, finalizedCheckpoint, nil -} diff --git a/testing/spectest/shared/altair/finality/BUILD.bazel b/testing/spectest/shared/altair/finality/BUILD.bazel index ee5c4c70951e..946c9bd82e5e 100644 --- a/testing/spectest/shared/altair/finality/BUILD.bazel +++ b/testing/spectest/shared/altair/finality/BUILD.bazel @@ -17,6 +17,7 @@ go_library( "//testing/spectest/utils:go_default_library", "//testing/util:go_default_library", "@com_github_golang_snappy//:go_default_library", + "@com_github_sirupsen_logrus//:go_default_library", "@org_golang_google_protobuf//proto:go_default_library", ], ) From c5ec69068d3f401edf475e46b3697960bc9f3c56 Mon Sep 17 00:00:00 2001 From: Potuz Date: Sun, 22 May 2022 10:41:09 -0300 Subject: [PATCH 13/28] gaz --- testing/spectest/shared/altair/finality/BUILD.bazel | 1 - 1 file changed, 1 deletion(-) diff --git a/testing/spectest/shared/altair/finality/BUILD.bazel b/testing/spectest/shared/altair/finality/BUILD.bazel index 946c9bd82e5e..ee5c4c70951e 100644 --- a/testing/spectest/shared/altair/finality/BUILD.bazel +++ b/testing/spectest/shared/altair/finality/BUILD.bazel @@ -17,7 +17,6 @@ go_library( "//testing/spectest/utils:go_default_library", "//testing/util:go_default_library", "@com_github_golang_snappy//:go_default_library", - "@com_github_sirupsen_logrus//:go_default_library", "@org_golang_google_protobuf//proto:go_default_library", ], ) From fe8cfd87a5a2a2a715ed7df4b2cef4d2f47724d2 Mon Sep 17 00:00:00 2001 From: Potuz Date: Sun, 22 May 2022 13:10:47 -0300 Subject: [PATCH 14/28] keep finalized checkpoint if nothing justified --- .../core/epoch/precompute/justification_finalization.go | 7 +++---- .../spectest/shared/phase0/epoch_processing/BUILD.bazel | 1 + 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/beacon-chain/core/epoch/precompute/justification_finalization.go b/beacon-chain/core/epoch/precompute/justification_finalization.go index 018fdfc74c9b..e8ce5b20a53d 100644 --- a/beacon-chain/core/epoch/precompute/justification_finalization.go +++ b/beacon-chain/core/epoch/precompute/justification_finalization.go @@ -128,8 +128,8 @@ func ComputeCheckpoints(state state.BeaconState, newBits bitfield.Bitvector4) (* oldPrevJustifiedCheckpoint := state.PreviousJustifiedCheckpoint() oldCurrJustifiedCheckpoint := state.CurrentJustifiedCheckpoint() - justifiedCheckpoint := ðpb.Checkpoint{} - finalizedCheckpoint := ðpb.Checkpoint{} + justifiedCheckpoint := oldCurrJustifiedCheckpoint + finalizedCheckpoint := state.FinalizedCheckpoint() // If 2/3 or more of the total balance attested in the current epoch. if newBits.BitAt(0) { @@ -151,8 +151,7 @@ func ComputeCheckpoints(state state.BeaconState, newBits bitfield.Bitvector4) (* // Process finalization according to Ethereum Beacon Chain specification. if len(newBits) == 0 { - finalizedCheckpoint = state.FinalizedCheckpoint() - return oldCurrJustifiedCheckpoint, finalizedCheckpoint, nil + return justifiedCheckpoint, finalizedCheckpoint, nil } justification := newBits.Bytes()[0] diff --git a/testing/spectest/shared/phase0/epoch_processing/BUILD.bazel b/testing/spectest/shared/phase0/epoch_processing/BUILD.bazel index 6569928e5f94..18c116bb10a5 100644 --- a/testing/spectest/shared/phase0/epoch_processing/BUILD.bazel +++ b/testing/spectest/shared/phase0/epoch_processing/BUILD.bazel @@ -30,6 +30,7 @@ go_library( "//testing/spectest/utils:go_default_library", "//testing/util:go_default_library", "@com_github_golang_snappy//:go_default_library", + "@com_github_sirupsen_logrus//:go_default_library", "@io_bazel_rules_go//go/tools/bazel:go_default_library", "@org_golang_google_protobuf//proto:go_default_library", ], From c3cdc57df6eb2d0fca6f6377e789bfbee1dd6bbf Mon Sep 17 00:00:00 2001 From: Potuz Date: Sun, 22 May 2022 13:11:54 -0300 Subject: [PATCH 15/28] gaz --- testing/spectest/shared/phase0/epoch_processing/BUILD.bazel | 1 - 1 file changed, 1 deletion(-) diff --git a/testing/spectest/shared/phase0/epoch_processing/BUILD.bazel b/testing/spectest/shared/phase0/epoch_processing/BUILD.bazel index 18c116bb10a5..6569928e5f94 100644 --- a/testing/spectest/shared/phase0/epoch_processing/BUILD.bazel +++ b/testing/spectest/shared/phase0/epoch_processing/BUILD.bazel @@ -30,7 +30,6 @@ go_library( "//testing/spectest/utils:go_default_library", "//testing/util:go_default_library", "@com_github_golang_snappy//:go_default_library", - "@com_github_sirupsen_logrus//:go_default_library", "@io_bazel_rules_go//go/tools/bazel:go_default_library", "@org_golang_google_protobuf//proto:go_default_library", ], From eba8a3679230c933ce63b893e6e4aac745330ca9 Mon Sep 17 00:00:00 2001 From: Potuz Date: Sun, 22 May 2022 14:02:13 -0300 Subject: [PATCH 16/28] copy checkpoint --- .../core/epoch/precompute/justification_finalization.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beacon-chain/core/epoch/precompute/justification_finalization.go b/beacon-chain/core/epoch/precompute/justification_finalization.go index e8ce5b20a53d..eb1f19428fc6 100644 --- a/beacon-chain/core/epoch/precompute/justification_finalization.go +++ b/beacon-chain/core/epoch/precompute/justification_finalization.go @@ -128,7 +128,7 @@ func ComputeCheckpoints(state state.BeaconState, newBits bitfield.Bitvector4) (* oldPrevJustifiedCheckpoint := state.PreviousJustifiedCheckpoint() oldCurrJustifiedCheckpoint := state.CurrentJustifiedCheckpoint() - justifiedCheckpoint := oldCurrJustifiedCheckpoint + justifiedCheckpoint := state.CurrentJustifiedCheckpoint() finalizedCheckpoint := state.FinalizedCheckpoint() // If 2/3 or more of the total balance attested in the current epoch. From 96b42b04caabcdfc4164ba67154fb412d867c69f Mon Sep 17 00:00:00 2001 From: Potuz Date: Sun, 22 May 2022 14:36:49 -0300 Subject: [PATCH 17/28] fix check for nil --- beacon-chain/core/altair/epoch_precompute_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/beacon-chain/core/altair/epoch_precompute_test.go b/beacon-chain/core/altair/epoch_precompute_test.go index c2a48260f67e..034062056faa 100644 --- a/beacon-chain/core/altair/epoch_precompute_test.go +++ b/beacon-chain/core/altair/epoch_precompute_test.go @@ -96,8 +96,8 @@ func TestUnrealizedCheckpoints(t *testing.T) { require.NoError(t, err) jc, fc, err := UnrealizedCheckpoints(s) require.NoError(t, err) - require.Equal(t, types.Epoch(0), jc.Epoch) - require.Equal(t, types.Epoch(0), fc.Epoch) + require.Equal(t, (*ethpb.Checkpoint)(nil), jc) + require.Equal(t, (*ethpb.Checkpoint)(nil), fc) } func TestProcessEpochParticipation(t *testing.T) { From e85f3cd3d08aba9960aad821853c3f7efcf87c9d Mon Sep 17 00:00:00 2001 From: Potuz Date: Sun, 22 May 2022 16:01:49 -0300 Subject: [PATCH 18/28] Add state package tests --- beacon-chain/state/state-native/BUILD.bazel | 1 + .../getters_participation_test.go | 64 +++++++++++++++++++ beacon-chain/state/v2/BUILD.bazel | 1 + .../state/v2/getters_participation_test.go | 64 +++++++++++++++++++ beacon-chain/state/v3/BUILD.bazel | 1 + .../state/v3/getters_participation_test.go | 64 +++++++++++++++++++ 6 files changed, 195 insertions(+) create mode 100644 beacon-chain/state/state-native/getters_participation_test.go create mode 100644 beacon-chain/state/v2/getters_participation_test.go create mode 100644 beacon-chain/state/v3/getters_participation_test.go diff --git a/beacon-chain/state/state-native/BUILD.bazel b/beacon-chain/state/state-native/BUILD.bazel index f1c9e569de52..984f45b2a8d0 100644 --- a/beacon-chain/state/state-native/BUILD.bazel +++ b/beacon-chain/state/state-native/BUILD.bazel @@ -86,6 +86,7 @@ go_test( "getters_attestation_test.go", "getters_block_test.go", "getters_checkpoint_test.go", + "getters_participation_test.go", "getters_test.go", "getters_validator_test.go", "hasher_test.go", diff --git a/beacon-chain/state/state-native/getters_participation_test.go b/beacon-chain/state/state-native/getters_participation_test.go new file mode 100644 index 000000000000..30fbdd647a5c --- /dev/null +++ b/beacon-chain/state/state-native/getters_participation_test.go @@ -0,0 +1,64 @@ +package state_native + +import ( + "testing" + + "github.com/prysmaticlabs/prysm/config/params" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/testing/require" +) + +func TestState_UnrealizedCheckpointBalances(t *testing.T) { + validators := make([]*ethpb.Validator, params.BeaconConfig().MinGenesisActiveValidatorCount) + balances := make([]uint64, params.BeaconConfig().MinGenesisActiveValidatorCount) + for i := 0; i < len(validators); i++ { + validators[i] = ðpb.Validator{ + ExitEpoch: params.BeaconConfig().FarFutureEpoch, + EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, + } + balances[i] = params.BeaconConfig().MaxEffectiveBalance + } + base := ðpb.BeaconStateAltair{ + Slot: 2, + RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector), + + Validators: validators, + CurrentEpochParticipation: make([]byte, params.BeaconConfig().MinGenesisActiveValidatorCount), + PreviousEpochParticipation: make([]byte, params.BeaconConfig().MinGenesisActiveValidatorCount), + Balances: balances, + } + state, err := InitializeFromProtoAltair(base) + require.NoError(t, err) + + // No one voted in the last two epochs + allActive := params.BeaconConfig().MinGenesisActiveValidatorCount * params.BeaconConfig().MaxEffectiveBalance + active, previous, current, err := state.UnrealizedCheckpointBalances() + require.NoError(t, err) + require.Equal(t, allActive, active) + require.Equal(t, uint64(0), current) + require.Equal(t, uint64(0), previous) + + // Add some votes in the last two epochs: + base.CurrentEpochParticipation[0] = 0xFF + base.PreviousEpochParticipation[0] = 0xFF + base.PreviousEpochParticipation[1] = 0xFF + + state, err = InitializeFromProtoAltair(base) + require.NoError(t, err) + active, previous, current, err = state.UnrealizedCheckpointBalances() + require.NoError(t, err) + require.Equal(t, allActive, active) + require.Equal(t, params.BeaconConfig().MaxEffectiveBalance, current) + require.Equal(t, 2*params.BeaconConfig().MaxEffectiveBalance, previous) + + // Slash some validators + validators[0].Slashed = true + state, err = InitializeFromProtoAltair(base) + require.NoError(t, err) + active, previous, current, err = state.UnrealizedCheckpointBalances() + require.NoError(t, err) + require.Equal(t, allActive-params.BeaconConfig().MaxEffectiveBalance, active) + require.Equal(t, uint64(0), current) + require.Equal(t, params.BeaconConfig().MaxEffectiveBalance, previous) + +} diff --git a/beacon-chain/state/v2/BUILD.bazel b/beacon-chain/state/v2/BUILD.bazel index 169c27599319..9dbf0b322818 100644 --- a/beacon-chain/state/v2/BUILD.bazel +++ b/beacon-chain/state/v2/BUILD.bazel @@ -65,6 +65,7 @@ go_test( "deprecated_setters_test.go", "getters_block_test.go", "getters_checkpoint_test.go", + "getters_participation_test.go", "getters_test.go", "getters_validator_test.go", "proofs_test.go", diff --git a/beacon-chain/state/v2/getters_participation_test.go b/beacon-chain/state/v2/getters_participation_test.go new file mode 100644 index 000000000000..bbe574e52d81 --- /dev/null +++ b/beacon-chain/state/v2/getters_participation_test.go @@ -0,0 +1,64 @@ +package v2 + +import ( + "testing" + + "github.com/prysmaticlabs/prysm/config/params" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/testing/require" +) + +func TestState_UnrealizedCheckpointBalances(t *testing.T) { + validators := make([]*ethpb.Validator, params.BeaconConfig().MinGenesisActiveValidatorCount) + balances := make([]uint64, params.BeaconConfig().MinGenesisActiveValidatorCount) + for i := 0; i < len(validators); i++ { + validators[i] = ðpb.Validator{ + ExitEpoch: params.BeaconConfig().FarFutureEpoch, + EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, + } + balances[i] = params.BeaconConfig().MaxEffectiveBalance + } + base := ðpb.BeaconStateAltair{ + Slot: 2, + RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector), + + Validators: validators, + CurrentEpochParticipation: make([]byte, params.BeaconConfig().MinGenesisActiveValidatorCount), + PreviousEpochParticipation: make([]byte, params.BeaconConfig().MinGenesisActiveValidatorCount), + Balances: balances, + } + state, err := InitializeFromProto(base) + require.NoError(t, err) + + // No one voted in the last two epochs + allActive := params.BeaconConfig().MinGenesisActiveValidatorCount * params.BeaconConfig().MaxEffectiveBalance + active, previous, current, err := state.UnrealizedCheckpointBalances() + require.NoError(t, err) + require.Equal(t, allActive, active) + require.Equal(t, uint64(0), current) + require.Equal(t, uint64(0), previous) + + // Add some votes in the last two epochs: + base.CurrentEpochParticipation[0] = 0xFF + base.PreviousEpochParticipation[0] = 0xFF + base.PreviousEpochParticipation[1] = 0xFF + + state, err = InitializeFromProto(base) + require.NoError(t, err) + active, previous, current, err = state.UnrealizedCheckpointBalances() + require.NoError(t, err) + require.Equal(t, allActive, active) + require.Equal(t, params.BeaconConfig().MaxEffectiveBalance, current) + require.Equal(t, 2*params.BeaconConfig().MaxEffectiveBalance, previous) + + // Slash some validators + validators[0].Slashed = true + state, err = InitializeFromProto(base) + require.NoError(t, err) + active, previous, current, err = state.UnrealizedCheckpointBalances() + require.NoError(t, err) + require.Equal(t, allActive-params.BeaconConfig().MaxEffectiveBalance, active) + require.Equal(t, uint64(0), current) + require.Equal(t, params.BeaconConfig().MaxEffectiveBalance, previous) + +} diff --git a/beacon-chain/state/v3/BUILD.bazel b/beacon-chain/state/v3/BUILD.bazel index 8b763a8e2ea4..86454da5f5ad 100644 --- a/beacon-chain/state/v3/BUILD.bazel +++ b/beacon-chain/state/v3/BUILD.bazel @@ -67,6 +67,7 @@ go_test( "deprecated_setters_test.go", "getters_block_test.go", "getters_checkpoint_test.go", + "getters_participation_test.go", "getters_test.go", "getters_validator_test.go", "proofs_test.go", diff --git a/beacon-chain/state/v3/getters_participation_test.go b/beacon-chain/state/v3/getters_participation_test.go new file mode 100644 index 000000000000..1b92ef04af50 --- /dev/null +++ b/beacon-chain/state/v3/getters_participation_test.go @@ -0,0 +1,64 @@ +package v3 + +import ( + "testing" + + "github.com/prysmaticlabs/prysm/config/params" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/testing/require" +) + +func TestState_UnrealizedCheckpointBalances(t *testing.T) { + validators := make([]*ethpb.Validator, params.BeaconConfig().MinGenesisActiveValidatorCount) + balances := make([]uint64, params.BeaconConfig().MinGenesisActiveValidatorCount) + for i := 0; i < len(validators); i++ { + validators[i] = ðpb.Validator{ + ExitEpoch: params.BeaconConfig().FarFutureEpoch, + EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, + } + balances[i] = params.BeaconConfig().MaxEffectiveBalance + } + base := ðpb.BeaconStateBellatrix{ + Slot: 2, + RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector), + + Validators: validators, + CurrentEpochParticipation: make([]byte, params.BeaconConfig().MinGenesisActiveValidatorCount), + PreviousEpochParticipation: make([]byte, params.BeaconConfig().MinGenesisActiveValidatorCount), + Balances: balances, + } + state, err := InitializeFromProto(base) + require.NoError(t, err) + + // No one voted in the last two epochs + allActive := params.BeaconConfig().MinGenesisActiveValidatorCount * params.BeaconConfig().MaxEffectiveBalance + active, previous, current, err := state.UnrealizedCheckpointBalances() + require.NoError(t, err) + require.Equal(t, allActive, active) + require.Equal(t, uint64(0), current) + require.Equal(t, uint64(0), previous) + + // Add some votes in the last two epochs: + base.CurrentEpochParticipation[0] = 0xFF + base.PreviousEpochParticipation[0] = 0xFF + base.PreviousEpochParticipation[1] = 0xFF + + state, err = InitializeFromProto(base) + require.NoError(t, err) + active, previous, current, err = state.UnrealizedCheckpointBalances() + require.NoError(t, err) + require.Equal(t, allActive, active) + require.Equal(t, params.BeaconConfig().MaxEffectiveBalance, current) + require.Equal(t, 2*params.BeaconConfig().MaxEffectiveBalance, previous) + + // Slash some validators + validators[0].Slashed = true + state, err = InitializeFromProto(base) + require.NoError(t, err) + active, previous, current, err = state.UnrealizedCheckpointBalances() + require.NoError(t, err) + require.Equal(t, allActive-params.BeaconConfig().MaxEffectiveBalance, active) + require.Equal(t, uint64(0), current) + require.Equal(t, params.BeaconConfig().MaxEffectiveBalance, previous) + +} From 48ed11426780ffae6a2cfaf9aa79128ecbade58e Mon Sep 17 00:00:00 2001 From: Potuz Date: Sun, 22 May 2022 16:24:00 -0300 Subject: [PATCH 19/28] Add tests --- .../core/altair/epoch_precompute_test.go | 37 ++++++++++++++++--- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/beacon-chain/core/altair/epoch_precompute_test.go b/beacon-chain/core/altair/epoch_precompute_test.go index 034062056faa..543bda029554 100644 --- a/beacon-chain/core/altair/epoch_precompute_test.go +++ b/beacon-chain/core/altair/epoch_precompute_test.go @@ -90,14 +90,41 @@ func TestInitializeEpochValidators_BadState(t *testing.T) { } func TestUnrealizedCheckpoints(t *testing.T) { - s, err := testState() + validators := make([]*ethpb.Validator, params.BeaconConfig().MinGenesisActiveValidatorCount) + balances := make([]uint64, params.BeaconConfig().MinGenesisActiveValidatorCount) + for i := 0; i < len(validators); i++ { + validators[i] = ðpb.Validator{ + ExitEpoch: params.BeaconConfig().FarFutureEpoch, + EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, + } + balances[i] = params.BeaconConfig().MaxEffectiveBalance + } + pr := [32]byte{'p'} + cr := [32]byte{'c'} + jcp := ðpb.Checkpoint{Root: cr[:], Epoch: 2} + fcp := ðpb.Checkpoint{Root: pr[:], Epoch: 1} + base := ðpb.BeaconStateAltair{ + Slot: 2, + RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector), + + Validators: validators, + CurrentEpochParticipation: make([]byte, params.BeaconConfig().MinGenesisActiveValidatorCount), + PreviousEpochParticipation: make([]byte, params.BeaconConfig().MinGenesisActiveValidatorCount), + InactivityScores: make([]uint64, params.BeaconConfig().MinGenesisActiveValidatorCount), + Balances: balances, + PreviousJustifiedCheckpoint: ðpb.Checkpoint{Root: pr[:], Epoch: 1}, + CurrentJustifiedCheckpoint: jcp, + FinalizedCheckpoint: fcp, + } + state, err := stateAltair.InitializeFromProto(base) require.NoError(t, err) - _, _, err = InitializePrecomputeValidators(context.Background(), s) + + _, _, err = InitializePrecomputeValidators(context.Background(), state) require.NoError(t, err) - jc, fc, err := UnrealizedCheckpoints(s) + jc, fc, err := UnrealizedCheckpoints(state) require.NoError(t, err) - require.Equal(t, (*ethpb.Checkpoint)(nil), jc) - require.Equal(t, (*ethpb.Checkpoint)(nil), fc) + require.DeepEqual(t, jcp, jc) + require.DeepEqual(t, fcp, fc) } func TestProcessEpochParticipation(t *testing.T) { From 234d4e14c29a4afc012d64dabc155d7c97e084f3 Mon Sep 17 00:00:00 2001 From: Potuz Date: Sun, 22 May 2022 20:54:14 -0300 Subject: [PATCH 20/28] Radek's review --- beacon-chain/state/state-native/getters_participation.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/beacon-chain/state/state-native/getters_participation.go b/beacon-chain/state/state-native/getters_participation.go index 52db5696d59a..d4af6e9e210c 100644 --- a/beacon-chain/state/state-native/getters_participation.go +++ b/beacon-chain/state/state-native/getters_participation.go @@ -43,6 +43,10 @@ func (b *BeaconState) PreviousEpochParticipation() ([]byte, error) { // current epoch and target attested in previous epoch. This function is used to // compute the "unrealized justification" that a synced Beacon Block will have. func (b *BeaconState) UnrealizedCheckpointBalances() (uint64, uint64, uint64, error) { + if b.version == version.Phase0 { + return 0, 0, 0, errNotSupported("UnrealizedCheckpointBalances", b.version) + } + b.lock.RLock() defer b.lock.RUnlock() From f442614de55d617ef75cddb40e85ee61be43168e Mon Sep 17 00:00:00 2001 From: Potuz Date: Sun, 22 May 2022 22:36:00 -0300 Subject: [PATCH 21/28] add more tests --- .../core/altair/epoch_precompute_test.go | 137 ++++++++++++++---- 1 file changed, 112 insertions(+), 25 deletions(-) diff --git a/beacon-chain/core/altair/epoch_precompute_test.go b/beacon-chain/core/altair/epoch_precompute_test.go index 543bda029554..69dbd729d903 100644 --- a/beacon-chain/core/altair/epoch_precompute_test.go +++ b/beacon-chain/core/altair/epoch_precompute_test.go @@ -5,6 +5,7 @@ import ( "math" "testing" + "github.com/prysmaticlabs/go-bitfield" "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute" "github.com/prysmaticlabs/prysm/beacon-chain/state" stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state/v2" @@ -91,7 +92,7 @@ func TestInitializeEpochValidators_BadState(t *testing.T) { func TestUnrealizedCheckpoints(t *testing.T) { validators := make([]*ethpb.Validator, params.BeaconConfig().MinGenesisActiveValidatorCount) - balances := make([]uint64, params.BeaconConfig().MinGenesisActiveValidatorCount) + balances := make([]uint64, len(validators)) for i := 0; i < len(validators); i++ { validators[i] = ðpb.Validator{ ExitEpoch: params.BeaconConfig().FarFutureEpoch, @@ -99,32 +100,118 @@ func TestUnrealizedCheckpoints(t *testing.T) { } balances[i] = params.BeaconConfig().MaxEffectiveBalance } - pr := [32]byte{'p'} - cr := [32]byte{'c'} - jcp := ðpb.Checkpoint{Root: cr[:], Epoch: 2} - fcp := ðpb.Checkpoint{Root: pr[:], Epoch: 1} - base := ðpb.BeaconStateAltair{ - Slot: 2, - RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector), - - Validators: validators, - CurrentEpochParticipation: make([]byte, params.BeaconConfig().MinGenesisActiveValidatorCount), - PreviousEpochParticipation: make([]byte, params.BeaconConfig().MinGenesisActiveValidatorCount), - InactivityScores: make([]uint64, params.BeaconConfig().MinGenesisActiveValidatorCount), - Balances: balances, - PreviousJustifiedCheckpoint: ðpb.Checkpoint{Root: pr[:], Epoch: 1}, - CurrentJustifiedCheckpoint: jcp, - FinalizedCheckpoint: fcp, + pjr := [32]byte{'p'} + cjr := [32]byte{'c'} + je := types.Epoch(3) + fe := types.Epoch(2) + pjcp := ðpb.Checkpoint{Root: pjr[:], Epoch: fe} + cjcp := ðpb.Checkpoint{Root: cjr[:], Epoch: je} + fcp := ðpb.Checkpoint{Root: pjr[:], Epoch: fe} + tests := []struct { + name string + slot types.Slot + prevVals, currVals int + expectedJustified, expectedFinalized types.Epoch // The expected unrealized checkpoint epochs + }{ + { + "Not enough votes, keep previous justification", + 129, + len(validators) / 3, + len(validators) / 3, + je, + fe, + }, + { + "Not enough votes, keep previous justification, N+2", + 161, + len(validators) / 3, + len(validators) / 3, + je, + fe, + }, + { + "Enough to justify previous epoch but not current", + 129, + 2*len(validators)/3 + 3, + len(validators) / 3, + je, + fe, + }, + { + "Enough to justify previous epoch but not current, N+2", + 161, + 2*len(validators)/3 + 3, + len(validators) / 3, + je + 1, + fe, + }, + { + "Enough to justify current epoch", + 129, + len(validators) / 3, + 2*len(validators)/3 + 3, + je + 1, + fe, + }, + { + "Enough to justify current epoch, but not previous", + 161, + len(validators) / 3, + 2*len(validators)/3 + 3, + je + 2, + fe, + }, + { + "Enough to justify current and previous", + 161, + 2*len(validators)/3 + 3, + 2*len(validators)/3 + 3, + je + 2, + fe, + }, } - state, err := stateAltair.InitializeFromProto(base) - require.NoError(t, err) + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + base := ðpb.BeaconStateAltair{ + RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector), + + Validators: validators, + Slot: test.slot, + CurrentEpochParticipation: make([]byte, params.BeaconConfig().MinGenesisActiveValidatorCount), + PreviousEpochParticipation: make([]byte, params.BeaconConfig().MinGenesisActiveValidatorCount), + Balances: balances, + PreviousJustifiedCheckpoint: pjcp, + CurrentJustifiedCheckpoint: cjcp, + FinalizedCheckpoint: fcp, + InactivityScores: make([]uint64, len(validators)), + JustificationBits: make(bitfield.Bitvector4, 1), + } + for i := 0; i < test.prevVals; i++ { + base.PreviousEpochParticipation[i] = 0xFF + } + for i := 0; i < test.currVals; i++ { + base.CurrentEpochParticipation[i] = 0xFF + } + if test.slot > 130 { + base.JustificationBits.SetBitAt(2, true) + base.JustificationBits.SetBitAt(3, true) + } else { + base.JustificationBits.SetBitAt(1, true) + base.JustificationBits.SetBitAt(2, true) + } - _, _, err = InitializePrecomputeValidators(context.Background(), state) - require.NoError(t, err) - jc, fc, err := UnrealizedCheckpoints(state) - require.NoError(t, err) - require.DeepEqual(t, jcp, jc) - require.DeepEqual(t, fcp, fc) + state, err := stateAltair.InitializeFromProto(base) + require.NoError(t, err) + + _, _, err = InitializePrecomputeValidators(context.Background(), state) + require.NoError(t, err) + + jc, fc, err := UnrealizedCheckpoints(state) + require.NoError(t, err) + require.DeepEqual(t, test.expectedJustified, jc.Epoch) + require.DeepEqual(t, test.expectedFinalized, fc.Epoch) + }) + } } func TestProcessEpochParticipation(t *testing.T) { From 0d9b099e322cc63f085c07c9ebb1ca12a215f20b Mon Sep 17 00:00:00 2001 From: Potuz Date: Mon, 23 May 2022 13:32:27 -0300 Subject: [PATCH 22/28] Update beacon-chain/core/epoch/precompute/justification_finalization.go Co-authored-by: terencechain --- .../core/epoch/precompute/justification_finalization.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/beacon-chain/core/epoch/precompute/justification_finalization.go b/beacon-chain/core/epoch/precompute/justification_finalization.go index eb1f19428fc6..8e5346f04893 100644 --- a/beacon-chain/core/epoch/precompute/justification_finalization.go +++ b/beacon-chain/core/epoch/precompute/justification_finalization.go @@ -40,8 +40,7 @@ func ProcessJustificationAndFinalizationPreCompute(state state.BeaconState, pBal return weighJustificationAndFinalization(state, newBits) } -// ProcessJustificationBits processes the justification bits during epoch -// processing. +// ProcessJustificationBits processes the justification bits during epoch processing. func ProcessJustificationBits(state state.BeaconState, totalActiveBalance, prevEpochTargetBalance, currEpochTargetBalance uint64) bitfield.Bitvector4 { newBits := state.JustificationBits() newBits.Shift(1) From cea55fc98aec4a1f3922718ed54b5ee4d02c50c7 Mon Sep 17 00:00:00 2001 From: Potuz Date: Mon, 23 May 2022 17:11:10 -0300 Subject: [PATCH 23/28] deduplicate to stateutil --- beacon-chain/state/state-native/BUILD.bazel | 1 - .../state-native/getters_participation.go | 31 ++---------------- beacon-chain/state/stateutil/BUILD.bazel | 1 + beacon-chain/state/v2/BUILD.bazel | 1 - .../state/v2/getters_participation.go | 32 ++----------------- beacon-chain/state/v3/BUILD.bazel | 1 - .../state/v3/getters_participation.go | 32 ++----------------- 7 files changed, 7 insertions(+), 92 deletions(-) diff --git a/beacon-chain/state/state-native/BUILD.bazel b/beacon-chain/state/state-native/BUILD.bazel index 984f45b2a8d0..0d25317e80db 100644 --- a/beacon-chain/state/state-native/BUILD.bazel +++ b/beacon-chain/state/state-native/BUILD.bazel @@ -69,7 +69,6 @@ go_library( "//crypto/hash:go_default_library", "//encoding/bytesutil:go_default_library", "//encoding/ssz:go_default_library", - "//math:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//runtime/version:go_default_library", "@com_github_ferranbt_fastssz//:go_default_library", diff --git a/beacon-chain/state/state-native/getters_participation.go b/beacon-chain/state/state-native/getters_participation.go index d4af6e9e210c..e58e58a4f9fc 100644 --- a/beacon-chain/state/state-native/getters_participation.go +++ b/beacon-chain/state/state-native/getters_participation.go @@ -2,8 +2,7 @@ package state_native import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/time" - "github.com/prysmaticlabs/prysm/config/params" - "github.com/prysmaticlabs/prysm/math" + "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" "github.com/prysmaticlabs/prysm/runtime/version" ) @@ -56,35 +55,9 @@ func (b *BeaconState) UnrealizedCheckpointBalances() (uint64, uint64, uint64, er return 0, 0, 0, ErrNilParticipation } - targetIdx := params.BeaconConfig().TimelyTargetFlagIndex - activeBalance := uint64(0) - currentTarget := uint64(0) - prevTarget := uint64(0) currentEpoch := time.CurrentEpoch(b) + return stateutil.UnrealizedCheckpointBalances(cp, pp, b.validators, currentEpoch) - var err error - for i, v := range b.validators { - active := v.ActivationEpoch <= currentEpoch && currentEpoch < v.ExitEpoch - if active && !v.Slashed { - activeBalance, err = math.Add64(activeBalance, v.EffectiveBalance) - if err != nil { - return 0, 0, 0, err - } - if ((cp[i] >> targetIdx) & 1) == 1 { - currentTarget, err = math.Add64(currentTarget, v.EffectiveBalance) - if err != nil { - return 0, 0, 0, err - } - } - if ((pp[i] >> targetIdx) & 1) == 1 { - prevTarget, err = math.Add64(prevTarget, v.EffectiveBalance) - if err != nil { - return 0, 0, 0, err - } - } - } - } - return activeBalance, prevTarget, currentTarget, nil } // currentEpochParticipationVal corresponding to participation bits on the beacon chain. diff --git a/beacon-chain/state/stateutil/BUILD.bazel b/beacon-chain/state/stateutil/BUILD.bazel index 2b61856f0774..49c14c44a2eb 100644 --- a/beacon-chain/state/stateutil/BUILD.bazel +++ b/beacon-chain/state/stateutil/BUILD.bazel @@ -15,6 +15,7 @@ go_library( "state_hasher.go", "sync_committee.root.go", "trie_helpers.go", + "unrealized_justification.go", "validator_map_handler.go", "validator_root.go", ], diff --git a/beacon-chain/state/v2/BUILD.bazel b/beacon-chain/state/v2/BUILD.bazel index 9dbf0b322818..d92b4cce94f7 100644 --- a/beacon-chain/state/v2/BUILD.bazel +++ b/beacon-chain/state/v2/BUILD.bazel @@ -48,7 +48,6 @@ go_library( "//crypto/hash:go_default_library", "//encoding/bytesutil:go_default_library", "//encoding/ssz:go_default_library", - "//math:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//runtime/version:go_default_library", "@com_github_pkg_errors//:go_default_library", diff --git a/beacon-chain/state/v2/getters_participation.go b/beacon-chain/state/v2/getters_participation.go index 1e6c8bcdc237..d5de0b4b13b5 100644 --- a/beacon-chain/state/v2/getters_participation.go +++ b/beacon-chain/state/v2/getters_participation.go @@ -2,8 +2,7 @@ package v2 import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/time" - "github.com/prysmaticlabs/prysm/config/params" - "github.com/prysmaticlabs/prysm/math" + "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" ) // CurrentEpochParticipation corresponding to participation bits on the beacon chain. @@ -51,36 +50,9 @@ func (b *BeaconState) UnrealizedCheckpointBalances() (uint64, uint64, uint64, er if cp == nil || pp == nil { return 0, 0, 0, ErrNilParticipation } - - targetIdx := params.BeaconConfig().TimelyTargetFlagIndex - activeBalance := uint64(0) - currentTarget := uint64(0) - prevTarget := uint64(0) currentEpoch := time.CurrentEpoch(b) + return stateutil.UnrealizedCheckpointBalances(cp, pp, b.state.Validators, currentEpoch) - var err error - for i, v := range b.state.Validators { - active := v.ActivationEpoch <= currentEpoch && currentEpoch < v.ExitEpoch - if active && !v.Slashed { - activeBalance, err = math.Add64(activeBalance, v.EffectiveBalance) - if err != nil { - return 0, 0, 0, err - } - if ((cp[i] >> targetIdx) & 1) == 1 { - currentTarget, err = math.Add64(currentTarget, v.EffectiveBalance) - if err != nil { - return 0, 0, 0, err - } - } - if ((pp[i] >> targetIdx) & 1) == 1 { - prevTarget, err = math.Add64(prevTarget, v.EffectiveBalance) - if err != nil { - return 0, 0, 0, err - } - } - } - } - return activeBalance, prevTarget, currentTarget, nil } // currentEpochParticipation corresponding to participation bits on the beacon chain. diff --git a/beacon-chain/state/v3/BUILD.bazel b/beacon-chain/state/v3/BUILD.bazel index 86454da5f5ad..973cc0a9c18d 100644 --- a/beacon-chain/state/v3/BUILD.bazel +++ b/beacon-chain/state/v3/BUILD.bazel @@ -50,7 +50,6 @@ go_library( "//crypto/hash:go_default_library", "//encoding/bytesutil:go_default_library", "//encoding/ssz:go_default_library", - "//math:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//runtime/version:go_default_library", "@com_github_pkg_errors//:go_default_library", diff --git a/beacon-chain/state/v3/getters_participation.go b/beacon-chain/state/v3/getters_participation.go index a4c9261f78cc..c1f62383bb09 100644 --- a/beacon-chain/state/v3/getters_participation.go +++ b/beacon-chain/state/v3/getters_participation.go @@ -2,8 +2,7 @@ package v3 import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/time" - "github.com/prysmaticlabs/prysm/config/params" - "github.com/prysmaticlabs/prysm/math" + "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" ) // CurrentEpochParticipation corresponding to participation bits on the beacon chain. @@ -51,36 +50,9 @@ func (b *BeaconState) UnrealizedCheckpointBalances() (uint64, uint64, uint64, er if cp == nil || pp == nil { return 0, 0, 0, ErrNilParticipation } - - targetIdx := params.BeaconConfig().TimelyTargetFlagIndex - activeBalance := uint64(0) - currentTarget := uint64(0) - prevTarget := uint64(0) currentEpoch := time.CurrentEpoch(b) + return stateutil.UnrealizedCheckpointBalances(cp, pp, b.state.Validators, currentEpoch) - var err error - for i, v := range b.state.Validators { - active := v.ActivationEpoch <= currentEpoch && currentEpoch < v.ExitEpoch - if active && !v.Slashed { - activeBalance, err = math.Add64(activeBalance, v.EffectiveBalance) - if err != nil { - return 0, 0, 0, err - } - if ((cp[i] >> targetIdx) & 1) == 1 { - currentTarget, err = math.Add64(currentTarget, v.EffectiveBalance) - if err != nil { - return 0, 0, 0, err - } - } - if ((pp[i] >> targetIdx) & 1) == 1 { - prevTarget, err = math.Add64(prevTarget, v.EffectiveBalance) - if err != nil { - return 0, 0, 0, err - } - } - } - } - return activeBalance, prevTarget, currentTarget, nil } // currentEpochParticipation corresponding to participation bits on the beacon chain. From c87d2f9b9fca40b1f7cda467ee2eca7ba126a81b Mon Sep 17 00:00:00 2001 From: Potuz Date: Mon, 23 May 2022 17:15:34 -0300 Subject: [PATCH 24/28] missing file --- .../stateutil/unrealized_justification.go | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 beacon-chain/state/stateutil/unrealized_justification.go diff --git a/beacon-chain/state/stateutil/unrealized_justification.go b/beacon-chain/state/stateutil/unrealized_justification.go new file mode 100644 index 000000000000..f9d2d50b43ae --- /dev/null +++ b/beacon-chain/state/stateutil/unrealized_justification.go @@ -0,0 +1,39 @@ +package stateutil + +import ( + "github.com/prysmaticlabs/prysm/config/params" + types "github.com/prysmaticlabs/prysm/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/math" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +func UnrealizedCheckpointBalances(cp, pp []byte, validators []*ethpb.Validator, currentEpoch types.Epoch) (uint64, uint64, uint64, error) { + targetIdx := params.BeaconConfig().TimelyTargetFlagIndex + activeBalance := uint64(0) + currentTarget := uint64(0) + prevTarget := uint64(0) + + var err error + for i, v := range validators { + active := v.ActivationEpoch <= currentEpoch && currentEpoch < v.ExitEpoch + if active && !v.Slashed { + activeBalance, err = math.Add64(activeBalance, v.EffectiveBalance) + if err != nil { + return 0, 0, 0, err + } + if ((cp[i] >> targetIdx) & 1) == 1 { + currentTarget, err = math.Add64(currentTarget, v.EffectiveBalance) + if err != nil { + return 0, 0, 0, err + } + } + if ((pp[i] >> targetIdx) & 1) == 1 { + prevTarget, err = math.Add64(prevTarget, v.EffectiveBalance) + if err != nil { + return 0, 0, 0, err + } + } + } + } + return activeBalance, prevTarget, currentTarget, nil +} From 97f81284bb54cee87bb8de7df20b5af6bcf5b773 Mon Sep 17 00:00:00 2001 From: Potuz Date: Tue, 24 May 2022 16:00:48 -0300 Subject: [PATCH 25/28] Add stateutil test --- .../precompute/justification_finalization.go | 2 +- beacon-chain/state/stateutil/BUILD.bazel | 1 + .../stateutil/unrealized_justification.go | 4 + .../unrealized_justification_test.go | 95 +++++++++++++++++++ 4 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 beacon-chain/state/stateutil/unrealized_justification_test.go diff --git a/beacon-chain/core/epoch/precompute/justification_finalization.go b/beacon-chain/core/epoch/precompute/justification_finalization.go index 8e5346f04893..a084fb53e2dc 100644 --- a/beacon-chain/core/epoch/precompute/justification_finalization.go +++ b/beacon-chain/core/epoch/precompute/justification_finalization.go @@ -150,7 +150,7 @@ func ComputeCheckpoints(state state.BeaconState, newBits bitfield.Bitvector4) (* // Process finalization according to Ethereum Beacon Chain specification. if len(newBits) == 0 { - return justifiedCheckpoint, finalizedCheckpoint, nil + return nil, nil, errors.New("empty justification bits") } justification := newBits.Bytes()[0] diff --git a/beacon-chain/state/stateutil/BUILD.bazel b/beacon-chain/state/stateutil/BUILD.bazel index 49c14c44a2eb..a2952c6be174 100644 --- a/beacon-chain/state/stateutil/BUILD.bazel +++ b/beacon-chain/state/stateutil/BUILD.bazel @@ -58,6 +58,7 @@ go_test( "reference_bench_test.go", "state_root_test.go", "trie_helpers_test.go", + "unrealized_justification_test.go", "validator_root_test.go", ], embed = [":go_default_library"], diff --git a/beacon-chain/state/stateutil/unrealized_justification.go b/beacon-chain/state/stateutil/unrealized_justification.go index f9d2d50b43ae..78dd0e6a5207 100644 --- a/beacon-chain/state/stateutil/unrealized_justification.go +++ b/beacon-chain/state/stateutil/unrealized_justification.go @@ -1,6 +1,7 @@ package stateutil import ( + "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/config/params" types "github.com/prysmaticlabs/prysm/consensus-types/primitives" "github.com/prysmaticlabs/prysm/math" @@ -12,6 +13,9 @@ func UnrealizedCheckpointBalances(cp, pp []byte, validators []*ethpb.Validator, activeBalance := uint64(0) currentTarget := uint64(0) prevTarget := uint64(0) + if len(cp) < len(validators) || len(pp) < len(validators) { + return 0, 0, 0, errors.New("participation does not match validator set") + } var err error for i, v := range validators { diff --git a/beacon-chain/state/stateutil/unrealized_justification_test.go b/beacon-chain/state/stateutil/unrealized_justification_test.go new file mode 100644 index 000000000000..de4f5341b4cd --- /dev/null +++ b/beacon-chain/state/stateutil/unrealized_justification_test.go @@ -0,0 +1,95 @@ +package stateutil + +import ( + "testing" + + "github.com/prysmaticlabs/prysm/config/params" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/testing/require" +) + +func TestState_UnrealizedCheckpointBalances(t *testing.T) { + validators := make([]*ethpb.Validator, params.BeaconConfig().MinGenesisActiveValidatorCount) + targetFlag := params.BeaconConfig().TimelyTargetFlagIndex + expectedActive := params.BeaconConfig().MinGenesisActiveValidatorCount * params.BeaconConfig().MaxEffectiveBalance + + balances := make([]uint64, params.BeaconConfig().MinGenesisActiveValidatorCount) + for i := 0; i < len(validators); i++ { + validators[i] = ðpb.Validator{ + ExitEpoch: params.BeaconConfig().FarFutureEpoch, + EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, + } + balances[i] = params.BeaconConfig().MaxEffectiveBalance + } + cp := make([]byte, len(validators)) + pp := make([]byte, len(validators)) + + t.Run("No one voted last two epochs", func(tt *testing.T) { + active, previous, current, err := UnrealizedCheckpointBalances(cp, pp, validators, 0) + require.NoError(tt, err) + require.Equal(tt, expectedActive, active) + require.Equal(tt, uint64(0), current) + require.Equal(tt, uint64(0), previous) + }) + + t.Run("bad votes in last two epochs", func(tt *testing.T) { + copy(cp, []byte{0xFF ^ (1 << targetFlag), 0xFF ^ (1 << targetFlag), 0xFF ^ (1 << targetFlag), 0x00}) + copy(pp, []byte{0x00, 0x00, 0x00, 0x00}) + active, previous, current, err := UnrealizedCheckpointBalances(cp, pp, validators, 1) + require.NoError(tt, err) + require.Equal(tt, expectedActive, active) + require.Equal(tt, uint64(0), current) + require.Equal(tt, uint64(0), previous) + }) + + t.Run("two votes in last epoch", func(tt *testing.T) { + copy(cp, []byte{0xFF ^ (1 << targetFlag), 0xFF ^ (1 << targetFlag), 0xFF ^ (1 << targetFlag), 0x00, 1 << targetFlag, 1 << targetFlag}) + copy(pp, []byte{0x00, 0x00, 0x00, 0x00, 0xFF ^ (1 << targetFlag)}) + active, previous, current, err := UnrealizedCheckpointBalances(cp, pp, validators, 1) + require.NoError(tt, err) + require.Equal(tt, expectedActive, active) + require.Equal(tt, 2*params.BeaconConfig().MaxEffectiveBalance, current) + require.Equal(tt, uint64(0), previous) + }) + + t.Run("two votes in previous epoch", func(tt *testing.T) { + copy(cp, []byte{0x00, 0x00, 0x00, 0x00, 0xFF ^ (1 << targetFlag), 0x00}) + copy(pp, []byte{0xFF ^ (1 << targetFlag), 0xFF ^ (1 << targetFlag), 0xFF ^ (1 << targetFlag), 0x00, 1 << targetFlag, 1 << targetFlag}) + active, previous, current, err := UnrealizedCheckpointBalances(cp, pp, validators, 1) + require.NoError(tt, err) + require.Equal(tt, expectedActive, active) + require.Equal(tt, uint64(0), current) + require.Equal(tt, 2*params.BeaconConfig().MaxEffectiveBalance, previous) + }) + + t.Run("votes in both epochs, decreased balance in first validator", func(tt *testing.T) { + validators[0].EffectiveBalance = params.BeaconConfig().MaxEffectiveBalance - params.BeaconConfig().MinDepositAmount + copy(cp, []byte{0xFF, 0xFF, 0x00, 0x00, 0xFF ^ (1 << targetFlag), 0}) + copy(pp, []byte{0xFF ^ (1 << targetFlag), 0xFF ^ (1 << targetFlag), 0xFF ^ (1 << targetFlag), 0x00, 0xFF, 0xFF}) + active, previous, current, err := UnrealizedCheckpointBalances(cp, pp, validators, 1) + require.NoError(tt, err) + expectedActive -= params.BeaconConfig().MinDepositAmount + require.Equal(tt, expectedActive, active) + require.Equal(tt, 2*params.BeaconConfig().MaxEffectiveBalance-params.BeaconConfig().MinDepositAmount, current) + require.Equal(tt, 2*params.BeaconConfig().MaxEffectiveBalance, previous) + }) + + t.Run("slash a validator", func(tt *testing.T) { + validators[1].Slashed = true + active, previous, current, err := UnrealizedCheckpointBalances(cp, pp, validators, 1) + require.NoError(tt, err) + expectedActive -= params.BeaconConfig().MaxEffectiveBalance + require.Equal(tt, expectedActive, active) + require.Equal(tt, params.BeaconConfig().MaxEffectiveBalance-params.BeaconConfig().MinDepositAmount, current) + require.Equal(tt, 2*params.BeaconConfig().MaxEffectiveBalance, previous) + }) + t.Run("Exit a validator", func(tt *testing.T) { + validators[4].ExitEpoch = 1 + active, previous, current, err := UnrealizedCheckpointBalances(cp, pp, validators, 2) + require.NoError(tt, err) + expectedActive -= params.BeaconConfig().MaxEffectiveBalance + require.Equal(tt, expectedActive, active) + require.Equal(tt, params.BeaconConfig().MaxEffectiveBalance-params.BeaconConfig().MinDepositAmount, current) + require.Equal(tt, params.BeaconConfig().MaxEffectiveBalance, previous) + }) +} From cf12a5a62fd2bbacb74b7688b7050b569cd47bcd Mon Sep 17 00:00:00 2001 From: terence tsao Date: Tue, 24 May 2022 15:12:16 -0700 Subject: [PATCH 26/28] Minor refactor, don't export certain things --- beacon-chain/core/altair/epoch_precompute.go | 17 ----------- .../precompute/justification_finalization.go | 30 +++++++++++++++---- 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/beacon-chain/core/altair/epoch_precompute.go b/beacon-chain/core/altair/epoch_precompute.go index 3d80aa5a2d69..b137dedf7424 100644 --- a/beacon-chain/core/altair/epoch_precompute.go +++ b/beacon-chain/core/altair/epoch_precompute.go @@ -10,7 +10,6 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/state" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/math" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "go.opencensus.io/trace" ) @@ -347,19 +346,3 @@ func attestationDelta( return reward, penalty, nil } - -// UnrealizedCheckpoints returns the justification and finalization checkpoints of the -// given state as if it was progressed with empty slots until the next epoch. -func UnrealizedCheckpoints(st state.BeaconState) (*ethpb.Checkpoint, *ethpb.Checkpoint, error) { - if st == nil || st.IsNil() { - return nil, nil, errNilState - } - - activeBalance, prevTarget, currentTarget, err := st.UnrealizedCheckpointBalances() - if err != nil { - return nil, nil, err - } - - justification := precompute.ProcessJustificationBits(st, activeBalance, prevTarget, currentTarget) - return precompute.ComputeCheckpoints(st, justification) -} diff --git a/beacon-chain/core/epoch/precompute/justification_finalization.go b/beacon-chain/core/epoch/precompute/justification_finalization.go index a084fb53e2dc..0f01a027fd0e 100644 --- a/beacon-chain/core/epoch/precompute/justification_finalization.go +++ b/beacon-chain/core/epoch/precompute/justification_finalization.go @@ -10,6 +10,24 @@ import ( "github.com/prysmaticlabs/prysm/time/slots" ) +var errNilState = errors.New("nil state") + +// UnrealizedCheckpoints returns the justification and finalization checkpoints of the +// given state as if it was progressed with empty slots until the next epoch. +func UnrealizedCheckpoints(st state.BeaconState) (*ethpb.Checkpoint, *ethpb.Checkpoint, error) { + if st == nil || st.IsNil() { + return nil, nil, errNilState + } + + activeBalance, prevTarget, currentTarget, err := st.UnrealizedCheckpointBalances() + if err != nil { + return nil, nil, err + } + + justification := processJustificationBits(st, activeBalance, prevTarget, currentTarget) + return computeCheckpoints(st, justification) +} + // ProcessJustificationAndFinalizationPreCompute processes justification and finalization during // epoch processing. This is where a beacon node can justify and finalize a new epoch. // Note: this is an optimized version by passing in precomputed total and attesting balances. @@ -35,13 +53,13 @@ func ProcessJustificationAndFinalizationPreCompute(state state.BeaconState, pBal return state, nil } - newBits := ProcessJustificationBits(state, pBal.ActiveCurrentEpoch, pBal.PrevEpochTargetAttested, pBal.CurrentEpochTargetAttested) + newBits := processJustificationBits(state, pBal.ActiveCurrentEpoch, pBal.PrevEpochTargetAttested, pBal.CurrentEpochTargetAttested) return weighJustificationAndFinalization(state, newBits) } -// ProcessJustificationBits processes the justification bits during epoch processing. -func ProcessJustificationBits(state state.BeaconState, totalActiveBalance, prevEpochTargetBalance, currEpochTargetBalance uint64) bitfield.Bitvector4 { +// processJustificationBits processes the justification bits during epoch processing. +func processJustificationBits(state state.BeaconState, totalActiveBalance, prevEpochTargetBalance, currEpochTargetBalance uint64) bitfield.Bitvector4 { newBits := state.JustificationBits() newBits.Shift(1) // If 2/3 or more of total balance attested in the previous epoch. @@ -59,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 } @@ -82,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, @@ -121,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() From 776360baf8ea4ce7fc6e55d7c4b3b5d21e2863ff Mon Sep 17 00:00:00 2001 From: Potuz Date: Fri, 27 May 2022 10:26:05 -0300 Subject: [PATCH 27/28] Fix exports in tests --- .../core/altair/epoch_precompute_test.go | 125 ----------------- .../core/epoch/precompute/BUILD.bazel | 2 + .../justification_finalization_test.go | 127 ++++++++++++++++++ 3 files changed, 129 insertions(+), 125 deletions(-) diff --git a/beacon-chain/core/altair/epoch_precompute_test.go b/beacon-chain/core/altair/epoch_precompute_test.go index 69dbd729d903..7c4dbfd5b47f 100644 --- a/beacon-chain/core/altair/epoch_precompute_test.go +++ b/beacon-chain/core/altair/epoch_precompute_test.go @@ -5,7 +5,6 @@ import ( "math" "testing" - "github.com/prysmaticlabs/go-bitfield" "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute" "github.com/prysmaticlabs/prysm/beacon-chain/state" stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state/v2" @@ -90,130 +89,6 @@ func TestInitializeEpochValidators_BadState(t *testing.T) { require.ErrorContains(t, "num of validators is different than num of inactivity scores", err) } -func TestUnrealizedCheckpoints(t *testing.T) { - validators := make([]*ethpb.Validator, params.BeaconConfig().MinGenesisActiveValidatorCount) - balances := make([]uint64, len(validators)) - for i := 0; i < len(validators); i++ { - validators[i] = ðpb.Validator{ - ExitEpoch: params.BeaconConfig().FarFutureEpoch, - EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, - } - balances[i] = params.BeaconConfig().MaxEffectiveBalance - } - pjr := [32]byte{'p'} - cjr := [32]byte{'c'} - je := types.Epoch(3) - fe := types.Epoch(2) - pjcp := ðpb.Checkpoint{Root: pjr[:], Epoch: fe} - cjcp := ðpb.Checkpoint{Root: cjr[:], Epoch: je} - fcp := ðpb.Checkpoint{Root: pjr[:], Epoch: fe} - tests := []struct { - name string - slot types.Slot - prevVals, currVals int - expectedJustified, expectedFinalized types.Epoch // The expected unrealized checkpoint epochs - }{ - { - "Not enough votes, keep previous justification", - 129, - len(validators) / 3, - len(validators) / 3, - je, - fe, - }, - { - "Not enough votes, keep previous justification, N+2", - 161, - len(validators) / 3, - len(validators) / 3, - je, - fe, - }, - { - "Enough to justify previous epoch but not current", - 129, - 2*len(validators)/3 + 3, - len(validators) / 3, - je, - fe, - }, - { - "Enough to justify previous epoch but not current, N+2", - 161, - 2*len(validators)/3 + 3, - len(validators) / 3, - je + 1, - fe, - }, - { - "Enough to justify current epoch", - 129, - len(validators) / 3, - 2*len(validators)/3 + 3, - je + 1, - fe, - }, - { - "Enough to justify current epoch, but not previous", - 161, - len(validators) / 3, - 2*len(validators)/3 + 3, - je + 2, - fe, - }, - { - "Enough to justify current and previous", - 161, - 2*len(validators)/3 + 3, - 2*len(validators)/3 + 3, - je + 2, - fe, - }, - } - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - base := ðpb.BeaconStateAltair{ - RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector), - - Validators: validators, - Slot: test.slot, - CurrentEpochParticipation: make([]byte, params.BeaconConfig().MinGenesisActiveValidatorCount), - PreviousEpochParticipation: make([]byte, params.BeaconConfig().MinGenesisActiveValidatorCount), - Balances: balances, - PreviousJustifiedCheckpoint: pjcp, - CurrentJustifiedCheckpoint: cjcp, - FinalizedCheckpoint: fcp, - InactivityScores: make([]uint64, len(validators)), - JustificationBits: make(bitfield.Bitvector4, 1), - } - for i := 0; i < test.prevVals; i++ { - base.PreviousEpochParticipation[i] = 0xFF - } - for i := 0; i < test.currVals; i++ { - base.CurrentEpochParticipation[i] = 0xFF - } - if test.slot > 130 { - base.JustificationBits.SetBitAt(2, true) - base.JustificationBits.SetBitAt(3, true) - } else { - base.JustificationBits.SetBitAt(1, true) - base.JustificationBits.SetBitAt(2, true) - } - - state, err := stateAltair.InitializeFromProto(base) - require.NoError(t, err) - - _, _, err = InitializePrecomputeValidators(context.Background(), state) - require.NoError(t, err) - - jc, fc, err := UnrealizedCheckpoints(state) - require.NoError(t, err) - require.DeepEqual(t, test.expectedJustified, jc.Epoch) - require.DeepEqual(t, test.expectedFinalized, fc.Epoch) - }) - } -} - func TestProcessEpochParticipation(t *testing.T) { s, err := testState() require.NoError(t, err) diff --git a/beacon-chain/core/epoch/precompute/BUILD.bazel b/beacon-chain/core/epoch/precompute/BUILD.bazel index f9584c0a7be7..11c59d82cc90 100644 --- a/beacon-chain/core/epoch/precompute/BUILD.bazel +++ b/beacon-chain/core/epoch/precompute/BUILD.bazel @@ -44,11 +44,13 @@ go_test( ], embed = [":go_default_library"], deps = [ + "//beacon-chain/core/altair:go_default_library", "//beacon-chain/core/epoch:go_default_library", "//beacon-chain/core/helpers:go_default_library", "//beacon-chain/core/time:go_default_library", "//beacon-chain/state:go_default_library", "//beacon-chain/state/v1:go_default_library", + "//beacon-chain/state/v2:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", "//consensus-types/primitives:go_default_library", diff --git a/beacon-chain/core/epoch/precompute/justification_finalization_test.go b/beacon-chain/core/epoch/precompute/justification_finalization_test.go index e2065120ed5b..e8cdc2b1fbf3 100644 --- a/beacon-chain/core/epoch/precompute/justification_finalization_test.go +++ b/beacon-chain/core/epoch/precompute/justification_finalization_test.go @@ -1,11 +1,14 @@ package precompute_test import ( + "context" "testing" "github.com/prysmaticlabs/go-bitfield" + "github.com/prysmaticlabs/prysm/beacon-chain/core/altair" "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute" v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + v2 "github.com/prysmaticlabs/prysm/beacon-chain/state/v2" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/config/params" types "github.com/prysmaticlabs/prysm/consensus-types/primitives" @@ -123,3 +126,127 @@ func TestProcessJustificationAndFinalizationPreCompute_JustifyPrevEpoch(t *testi assert.DeepEqual(t, params.BeaconConfig().ZeroHash[:], newState.FinalizedCheckpoint().Root) assert.Equal(t, types.Epoch(0), newState.FinalizedCheckpointEpoch(), "Unexpected finalized epoch") } + +func TestUnrealizedCheckpoints(t *testing.T) { + validators := make([]*ethpb.Validator, params.BeaconConfig().MinGenesisActiveValidatorCount) + balances := make([]uint64, len(validators)) + for i := 0; i < len(validators); i++ { + validators[i] = ðpb.Validator{ + ExitEpoch: params.BeaconConfig().FarFutureEpoch, + EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, + } + balances[i] = params.BeaconConfig().MaxEffectiveBalance + } + pjr := [32]byte{'p'} + cjr := [32]byte{'c'} + je := types.Epoch(3) + fe := types.Epoch(2) + pjcp := ðpb.Checkpoint{Root: pjr[:], Epoch: fe} + cjcp := ðpb.Checkpoint{Root: cjr[:], Epoch: je} + fcp := ðpb.Checkpoint{Root: pjr[:], Epoch: fe} + tests := []struct { + name string + slot types.Slot + prevVals, currVals int + expectedJustified, expectedFinalized types.Epoch // The expected unrealized checkpoint epochs + }{ + { + "Not enough votes, keep previous justification", + 129, + len(validators) / 3, + len(validators) / 3, + je, + fe, + }, + { + "Not enough votes, keep previous justification, N+2", + 161, + len(validators) / 3, + len(validators) / 3, + je, + fe, + }, + { + "Enough to justify previous epoch but not current", + 129, + 2*len(validators)/3 + 3, + len(validators) / 3, + je, + fe, + }, + { + "Enough to justify previous epoch but not current, N+2", + 161, + 2*len(validators)/3 + 3, + len(validators) / 3, + je + 1, + fe, + }, + { + "Enough to justify current epoch", + 129, + len(validators) / 3, + 2*len(validators)/3 + 3, + je + 1, + fe, + }, + { + "Enough to justify current epoch, but not previous", + 161, + len(validators) / 3, + 2*len(validators)/3 + 3, + je + 2, + fe, + }, + { + "Enough to justify current and previous", + 161, + 2*len(validators)/3 + 3, + 2*len(validators)/3 + 3, + je + 2, + fe, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + base := ðpb.BeaconStateAltair{ + RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector), + + Validators: validators, + Slot: test.slot, + CurrentEpochParticipation: make([]byte, params.BeaconConfig().MinGenesisActiveValidatorCount), + PreviousEpochParticipation: make([]byte, params.BeaconConfig().MinGenesisActiveValidatorCount), + Balances: balances, + PreviousJustifiedCheckpoint: pjcp, + CurrentJustifiedCheckpoint: cjcp, + FinalizedCheckpoint: fcp, + InactivityScores: make([]uint64, len(validators)), + JustificationBits: make(bitfield.Bitvector4, 1), + } + for i := 0; i < test.prevVals; i++ { + base.PreviousEpochParticipation[i] = 0xFF + } + for i := 0; i < test.currVals; i++ { + base.CurrentEpochParticipation[i] = 0xFF + } + if test.slot > 130 { + base.JustificationBits.SetBitAt(2, true) + base.JustificationBits.SetBitAt(3, true) + } else { + base.JustificationBits.SetBitAt(1, true) + base.JustificationBits.SetBitAt(2, true) + } + + state, err := v2.InitializeFromProto(base) + require.NoError(t, err) + + _, _, err = altair.InitializePrecomputeValidators(context.Background(), state) + require.NoError(t, err) + + jc, fc, err := precompute.UnrealizedCheckpoints(state) + require.NoError(t, err) + require.DeepEqual(t, test.expectedJustified, jc.Epoch) + require.DeepEqual(t, test.expectedFinalized, fc.Epoch) + }) + } +} From 6fc925903c28828e518fb1480707bf17b2662cf1 Mon Sep 17 00:00:00 2001 From: Potuz Date: Fri, 27 May 2022 10:31:44 -0300 Subject: [PATCH 28/28] remove unused error --- beacon-chain/core/altair/BUILD.bazel | 1 - beacon-chain/core/altair/error.go | 5 ----- 2 files changed, 6 deletions(-) delete mode 100644 beacon-chain/core/altair/error.go diff --git a/beacon-chain/core/altair/BUILD.bazel b/beacon-chain/core/altair/BUILD.bazel index 7fa2f77495b3..dbe46a4d3391 100644 --- a/beacon-chain/core/altair/BUILD.bazel +++ b/beacon-chain/core/altair/BUILD.bazel @@ -8,7 +8,6 @@ go_library( "deposit.go", "epoch_precompute.go", "epoch_spec.go", - "error.go", "reward.go", "sync_committee.go", "transition.go", diff --git a/beacon-chain/core/altair/error.go b/beacon-chain/core/altair/error.go deleted file mode 100644 index 458b73b80336..000000000000 --- a/beacon-chain/core/altair/error.go +++ /dev/null @@ -1,5 +0,0 @@ -package altair - -import "github.com/pkg/errors" - -var errNilState = errors.New("nil state")