diff --git a/beacon-chain/blockchain/defragment.go b/beacon-chain/blockchain/defragment.go index fb501b7647..3d2f2287b3 100644 --- a/beacon-chain/blockchain/defragment.go +++ b/beacon-chain/blockchain/defragment.go @@ -2,7 +2,6 @@ package blockchain import ( "github.com/OffchainLabs/prysm/v6/beacon-chain/state" - "github.com/OffchainLabs/prysm/v6/config/features" "github.com/OffchainLabs/prysm/v6/time" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" @@ -17,9 +16,6 @@ var stateDefragmentationTime = promauto.NewSummary(prometheus.SummaryOpts{ // a higher number of fragmented indexes are reallocated to a new separate slice for // that field. func (s *Service) defragmentState(st state.BeaconState) { - if !features.Get().EnableExperimentalState { - return - } startTime := time.Now() st.Defragment() elapsedTime := time.Since(startTime) diff --git a/beacon-chain/blockchain/metrics_test.go b/beacon-chain/blockchain/metrics_test.go index ed8c572eb2..31a9cf72d8 100644 --- a/beacon-chain/blockchain/metrics_test.go +++ b/beacon-chain/blockchain/metrics_test.go @@ -8,16 +8,6 @@ import ( "github.com/OffchainLabs/prysm/v6/testing/util" ) -func TestReportEpochMetrics_BadHeadState(t *testing.T) { - s, err := util.NewBeaconState() - require.NoError(t, err) - h, err := util.NewBeaconState() - require.NoError(t, err) - require.NoError(t, h.SetValidators(nil)) - err = reportEpochMetrics(t.Context(), s, h) - require.ErrorContains(t, "failed to initialize precompute: state has nil validator slice", err) -} - func TestReportEpochMetrics_BadAttestation(t *testing.T) { s, err := util.NewBeaconState() require.NoError(t, err) diff --git a/beacon-chain/core/altair/reward_test.go b/beacon-chain/core/altair/reward_test.go index 90749d44f0..e33fea2564 100644 --- a/beacon-chain/core/altair/reward_test.go +++ b/beacon-chain/core/altair/reward_test.go @@ -31,7 +31,7 @@ func Test_BaseReward(t *testing.T) { valIdx: 2, st: genState(1), want: 0, - errString: "validator index 2 does not exist", + errString: "index 2 out of bounds", }, { name: "active balance is 32eth", @@ -89,7 +89,7 @@ func Test_BaseRewardWithTotalBalance(t *testing.T) { valIdx: 2, activeBalance: 1, want: 0, - errString: "validator index 2 does not exist", + errString: "index 2 out of bounds", }, { name: "active balance is 1", diff --git a/beacon-chain/core/blocks/block_operations_fuzz_test.go b/beacon-chain/core/blocks/block_operations_fuzz_test.go index d06278d486..f81e1bad61 100644 --- a/beacon-chain/core/blocks/block_operations_fuzz_test.go +++ b/beacon-chain/core/blocks/block_operations_fuzz_test.go @@ -119,6 +119,7 @@ func TestFuzzEth1DataHasEnoughSupport_10000(t *testing.T) { require.NoError(t, err) _, err = Eth1DataHasEnoughSupport(s, eth1data) _ = err + fuzz.FreeMemory(i) } } @@ -319,6 +320,7 @@ func TestFuzzverifyDeposit_10000(t *testing.T) { require.NoError(t, err) err = VerifyDeposit(s, deposit) _ = err + fuzz.FreeMemory(i) } } @@ -382,5 +384,6 @@ func TestFuzzVerifyExit_10000(t *testing.T) { _ = err err = VerifyExitAndSignature(val, s, ve) _ = err + fuzz.FreeMemory(i) } } diff --git a/beacon-chain/core/helpers/sync_committee_test.go b/beacon-chain/core/helpers/sync_committee_test.go index 183730df66..213dab8703 100644 --- a/beacon-chain/core/helpers/sync_committee_test.go +++ b/beacon-chain/core/helpers/sync_committee_test.go @@ -100,7 +100,7 @@ func TestIsCurrentEpochSyncCommittee_DoesNotExist(t *testing.T) { require.NoError(t, state.SetNextSyncCommittee(syncCommittee)) ok, err := helpers.IsCurrentPeriodSyncCommittee(state, 12390192) - require.ErrorContains(t, "validator index 12390192 does not exist", err) + require.ErrorContains(t, "index 12390192 out of bounds", err) require.Equal(t, false, ok) } @@ -187,7 +187,7 @@ func TestIsNextEpochSyncCommittee_DoesNotExist(t *testing.T) { require.NoError(t, state.SetNextSyncCommittee(syncCommittee)) ok, err := helpers.IsNextPeriodSyncCommittee(state, 120391029) - require.ErrorContains(t, "validator index 120391029 does not exist", err) + require.ErrorContains(t, "index 120391029 out of bounds", err) require.Equal(t, false, ok) } @@ -287,7 +287,7 @@ func TestCurrentEpochSyncSubcommitteeIndices_DoesNotExist(t *testing.T) { require.NoError(t, state.SetNextSyncCommittee(syncCommittee)) index, err := helpers.CurrentPeriodSyncSubcommitteeIndices(state, 129301923) - require.ErrorContains(t, "validator index 129301923 does not exist", err) + require.ErrorContains(t, "index 129301923 out of bounds", err) require.DeepEqual(t, []primitives.CommitteeIndex(nil), index) } @@ -374,7 +374,7 @@ func TestNextEpochSyncSubcommitteeIndices_DoesNotExist(t *testing.T) { require.NoError(t, state.SetNextSyncCommittee(syncCommittee)) index, err := helpers.NextPeriodSyncSubcommitteeIndices(state, 21093019) - require.ErrorContains(t, "validator index 21093019 does not exist", err) + require.ErrorContains(t, "index 21093019 out of bounds", err) require.DeepEqual(t, []primitives.CommitteeIndex(nil), index) } diff --git a/beacon-chain/core/helpers/validators_test.go b/beacon-chain/core/helpers/validators_test.go index 877c85e974..40d5b47572 100644 --- a/beacon-chain/core/helpers/validators_test.go +++ b/beacon-chain/core/helpers/validators_test.go @@ -561,17 +561,6 @@ func TestActiveValidatorIndices(t *testing.T) { }, want: []primitives.ValidatorIndex{0, 2, 3}, },*/ - { - name: "impossible_zero_validators", // Regression test for issue #13051 - args: args{ - state: ðpb.BeaconState{ - RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector), - Validators: make([]*ethpb.Validator, 0), - }, - epoch: 10, - }, - wantedErr: "state has nil validator slice", - }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/beacon-chain/rpc/eth/beacon/BUILD.bazel b/beacon-chain/rpc/eth/beacon/BUILD.bazel index 37a8df0cbe..824faeb098 100644 --- a/beacon-chain/rpc/eth/beacon/BUILD.bazel +++ b/beacon-chain/rpc/eth/beacon/BUILD.bazel @@ -46,11 +46,11 @@ go_library( "//config/features:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", - "//consensus-types:go_default_library", "//consensus-types/blocks:go_default_library", "//consensus-types/interfaces:go_default_library", "//consensus-types/primitives:go_default_library", "//consensus-types/validator:go_default_library", + "//container/multi-value-slice:go_default_library", "//crypto/bls:go_default_library", "//encoding/bytesutil:go_default_library", "//monitoring/tracing/trace:go_default_library", diff --git a/beacon-chain/rpc/eth/beacon/handlers_pool.go b/beacon-chain/rpc/eth/beacon/handlers_pool.go index c1c58fccbe..168519c307 100644 --- a/beacon-chain/rpc/eth/beacon/handlers_pool.go +++ b/beacon-chain/rpc/eth/beacon/handlers_pool.go @@ -22,8 +22,8 @@ import ( "github.com/OffchainLabs/prysm/v6/beacon-chain/rpc/eth/shared" "github.com/OffchainLabs/prysm/v6/config/features" "github.com/OffchainLabs/prysm/v6/config/params" - consensus_types "github.com/OffchainLabs/prysm/v6/consensus-types" "github.com/OffchainLabs/prysm/v6/consensus-types/primitives" + mvslice "github.com/OffchainLabs/prysm/v6/container/multi-value-slice" "github.com/OffchainLabs/prysm/v6/crypto/bls" "github.com/OffchainLabs/prysm/v6/monitoring/tracing/trace" "github.com/OffchainLabs/prysm/v6/network/httputil" @@ -501,7 +501,7 @@ func (s *Server) SubmitVoluntaryExit(w http.ResponseWriter, r *http.Request) { } val, err := headState.ValidatorAtIndexReadOnly(exit.Exit.ValidatorIndex) if err != nil { - if errors.Is(err, consensus_types.ErrOutOfBounds) { + if errors.Is(err, mvslice.ErrOutOfBounds) { httputil.HandleError(w, "Could not get validator: "+err.Error(), http.StatusBadRequest) return } diff --git a/beacon-chain/rpc/eth/events/events_test.go b/beacon-chain/rpc/eth/events/events_test.go index e8a6fcb628..74bab750ee 100644 --- a/beacon-chain/rpc/eth/events/events_test.go +++ b/beacon-chain/rpc/eth/events/events_test.go @@ -529,6 +529,7 @@ func TestStreamEvents_OperationsEvents(t *testing.T) { st := tc.getState() v := ð.Validator{ExitEpoch: math.MaxUint64, EffectiveBalance: params.BeaconConfig().MinActivationBalance, WithdrawalCredentials: make([]byte, 32)} require.NoError(t, st.SetValidators([]*eth.Validator{v})) + require.NoError(t, st.SetBalances([]uint64{0})) currentSlot := primitives.Slot(0) // to avoid slot processing require.NoError(t, st.SetSlot(currentSlot+1)) diff --git a/beacon-chain/rpc/eth/validator/BUILD.bazel b/beacon-chain/rpc/eth/validator/BUILD.bazel index 21be105298..f4d7f416a7 100644 --- a/beacon-chain/rpc/eth/validator/BUILD.bazel +++ b/beacon-chain/rpc/eth/validator/BUILD.bazel @@ -33,10 +33,10 @@ go_library( "//config/features:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", - "//consensus-types:go_default_library", "//consensus-types/blocks:go_default_library", "//consensus-types/primitives:go_default_library", "//consensus-types/validator:go_default_library", + "//container/multi-value-slice:go_default_library", "//crypto/bls/common:go_default_library", "//encoding/bytesutil:go_default_library", "//monitoring/tracing/trace:go_default_library", diff --git a/beacon-chain/rpc/eth/validator/handlers.go b/beacon-chain/rpc/eth/validator/handlers.go index ede89f7dd9..af4d216d23 100644 --- a/beacon-chain/rpc/eth/validator/handlers.go +++ b/beacon-chain/rpc/eth/validator/handlers.go @@ -26,9 +26,9 @@ import ( "github.com/OffchainLabs/prysm/v6/config/features" fieldparams "github.com/OffchainLabs/prysm/v6/config/fieldparams" "github.com/OffchainLabs/prysm/v6/config/params" - consensus_types "github.com/OffchainLabs/prysm/v6/consensus-types" "github.com/OffchainLabs/prysm/v6/consensus-types/primitives" validator2 "github.com/OffchainLabs/prysm/v6/consensus-types/validator" + mvslice "github.com/OffchainLabs/prysm/v6/container/multi-value-slice" "github.com/OffchainLabs/prysm/v6/encoding/bytesutil" "github.com/OffchainLabs/prysm/v6/monitoring/tracing/trace" "github.com/OffchainLabs/prysm/v6/network/httputil" @@ -570,7 +570,7 @@ func (s *Server) SubmitBeaconCommitteeSubscription(w http.ResponseWriter, r *htt subscriptions[i] = consensusItem val, err := st.ValidatorAtIndexReadOnly(consensusItem.ValidatorIndex) if err != nil { - if errors.Is(err, consensus_types.ErrOutOfBounds) { + if errors.Is(err, mvslice.ErrOutOfBounds) { httputil.HandleError(w, "Could not get validator: "+err.Error(), http.StatusBadRequest) return } diff --git a/beacon-chain/state/fieldtrie/BUILD.bazel b/beacon-chain/state/fieldtrie/BUILD.bazel index aff7432efc..2d5fa9e8ca 100644 --- a/beacon-chain/state/fieldtrie/BUILD.bazel +++ b/beacon-chain/state/fieldtrie/BUILD.bazel @@ -31,7 +31,6 @@ go_test( "//beacon-chain/state/state-native/custom-types:go_default_library", "//beacon-chain/state/state-native/types:go_default_library", "//beacon-chain/state/stateutil:go_default_library", - "//config/features:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", "//consensus-types/primitives:go_default_library", diff --git a/beacon-chain/state/fieldtrie/field_trie_test.go b/beacon-chain/state/fieldtrie/field_trie_test.go index d3fdad6678..34458c76b6 100644 --- a/beacon-chain/state/fieldtrie/field_trie_test.go +++ b/beacon-chain/state/fieldtrie/field_trie_test.go @@ -7,7 +7,6 @@ import ( customtypes "github.com/OffchainLabs/prysm/v6/beacon-chain/state/state-native/custom-types" "github.com/OffchainLabs/prysm/v6/beacon-chain/state/state-native/types" "github.com/OffchainLabs/prysm/v6/beacon-chain/state/stateutil" - "github.com/OffchainLabs/prysm/v6/config/features" "github.com/OffchainLabs/prysm/v6/config/params" "github.com/OffchainLabs/prysm/v6/consensus-types/primitives" mvslice "github.com/OffchainLabs/prysm/v6/container/multi-value-slice" @@ -21,32 +20,19 @@ func TestFieldTrie_NewTrie(t *testing.T) { t.Run("native state", func(t *testing.T) { runNewTrie(t) }) - t.Run("native state with multivalue slice", func(t *testing.T) { - cfg := &features.Flags{} - cfg.EnableExperimentalState = true - reset := features.InitWithReset(cfg) - runNewTrie(t) - - reset() - }) } func runNewTrie(t *testing.T) { newState, _ := util.DeterministicGenesisState(t, 40) roots := newState.BlockRoots() - var elements interface{} blockRoots := make([][32]byte, len(roots)) for i, r := range roots { blockRoots[i] = [32]byte(r) } - elements = customtypes.BlockRoots(blockRoots) - - if features.Get().EnableExperimentalState { - mvRoots := buildTestCompositeSlice[[32]byte](blockRoots) - elements = mvslice.MultiValueSliceComposite[[32]byte]{ - Identifiable: mockIdentifier{}, - MultiValueSlice: mvRoots, - } + mvRoots := buildTestCompositeSlice[[32]byte](blockRoots) + elements := mvslice.MultiValueSliceComposite[[32]byte]{ + Identifiable: mockIdentifier{}, + MultiValueSlice: mvRoots, } trie, err := NewFieldTrie(types.BlockRoots, types.BasicArray, elements, uint64(params.BeaconConfig().SlotsPerHistoricalRoot)) @@ -69,27 +55,15 @@ func TestFieldTrie_RecomputeTrie(t *testing.T) { t.Run("native state", func(t *testing.T) { runRecomputeTrie(t) }) - t.Run("native state with multivalue slice", func(t *testing.T) { - cfg := &features.Flags{} - cfg.EnableExperimentalState = true - reset := features.InitWithReset(cfg) - runRecomputeTrie(t) - - reset() - }) } func runRecomputeTrie(t *testing.T) { newState, _ := util.DeterministicGenesisState(t, 32) - var elements interface{} - elements = newState.Validators() - if features.Get().EnableExperimentalState { - mvRoots := buildTestCompositeSlice[*ethpb.Validator](newState.Validators()) - elements = mvslice.MultiValueSliceComposite[*ethpb.Validator]{ - Identifiable: mockIdentifier{}, - MultiValueSlice: mvRoots, - } + mvRoots := buildTestCompositeSlice[*ethpb.Validator](newState.Validators()) + elements := mvslice.MultiValueSliceComposite[*ethpb.Validator]{ + Identifiable: mockIdentifier{}, + MultiValueSlice: mvRoots, } trie, err := NewFieldTrie(types.Validators, types.CompositeArray, elements, params.BeaconConfig().ValidatorRegistryLimit) @@ -125,26 +99,14 @@ func TestFieldTrie_RecomputeTrie_CompressedArray(t *testing.T) { t.Run("native state", func(t *testing.T) { runRecomputeTrie_CompressedArray(t) }) - t.Run("native state with multivalue slice", func(t *testing.T) { - cfg := &features.Flags{} - cfg.EnableExperimentalState = true - reset := features.InitWithReset(cfg) - runRecomputeTrie_CompressedArray(t) - - reset() - }) } func runRecomputeTrie_CompressedArray(t *testing.T) { newState, _ := util.DeterministicGenesisState(t, 32) - var elements interface{} - elements = newState.Balances() - if features.Get().EnableExperimentalState { - mvBals := buildTestCompositeSlice(newState.Balances()) - elements = mvslice.MultiValueSliceComposite[uint64]{ - Identifiable: mockIdentifier{}, - MultiValueSlice: mvBals, - } + mvBals := buildTestCompositeSlice(newState.Balances()) + elements := mvslice.MultiValueSliceComposite[uint64]{ + Identifiable: mockIdentifier{}, + MultiValueSlice: mvBals, } trie, err := NewFieldTrie(types.Balances, types.CompressedArray, elements, stateutil.ValidatorLimitForBalancesChunks()) diff --git a/beacon-chain/state/state-native/BUILD.bazel b/beacon-chain/state/state-native/BUILD.bazel index 95694e091e..6d7b6d19c9 100644 --- a/beacon-chain/state/state-native/BUILD.bazel +++ b/beacon-chain/state/state-native/BUILD.bazel @@ -59,10 +59,8 @@ go_library( "//beacon-chain/state/state-native/custom-types:go_default_library", "//beacon-chain/state/state-native/types:go_default_library", "//beacon-chain/state/stateutil:go_default_library", - "//config/features:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", - "//consensus-types:go_default_library", "//consensus-types/blocks:go_default_library", "//consensus-types/interfaces:go_default_library", "//consensus-types/primitives:go_default_library", @@ -135,7 +133,6 @@ go_test( "//beacon-chain/state/state-native/types:go_default_library", "//beacon-chain/state/stateutil:go_default_library", "//beacon-chain/state/testing:go_default_library", - "//config/features:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", "//consensus-types/blocks:go_default_library", diff --git a/beacon-chain/state/state-native/README.md b/beacon-chain/state/state-native/README.md index c688086e7b..85d75e13d9 100644 --- a/beacon-chain/state/state-native/README.md +++ b/beacon-chain/state/state-native/README.md @@ -13,9 +13,7 @@ Add the new getter and setter to `/beacon-chain/state/interfaces.go`. - Update `spec_parameters.go`. - Update `state_trie.go`: - Add a `[version]Fields` variable that contains all fields of the new state version. - - Add a `[version]SharedFieldRefCount` constant that represents the number of fields whose references are shared between states. - - Add an `experimentalState[Version]SharedFieldCountRef` constant that represents the number of **non multi-value slice** fields whose references are shared -between states. + - Add a `[version]SharedFieldRefCount` constant that represents the number of fields whose references are shared between states. Multi-value slice references are not shared in this way so don't include them. - Add the following functions: `InitializeFromProto[Version]()`, `InitializeFromProtoUnsafe[Version]()`. - Update the following functions: `Copy()`, `initializeMerkleLayers()`, `RecordStateMetrics()` (applies only to multi-value slice fields), `rootSelector()`, `finalizerCleanup()` (applies only to multi-value slice fields). diff --git a/beacon-chain/state/state-native/beacon_state.go b/beacon-chain/state/state-native/beacon_state.go index d0be3373cf..ad68c548eb 100644 --- a/beacon-chain/state/state-native/beacon_state.go +++ b/beacon-chain/state/state-native/beacon_state.go @@ -8,7 +8,6 @@ import ( customtypes "github.com/OffchainLabs/prysm/v6/beacon-chain/state/state-native/custom-types" "github.com/OffchainLabs/prysm/v6/beacon-chain/state/state-native/types" "github.com/OffchainLabs/prysm/v6/beacon-chain/state/stateutil" - "github.com/OffchainLabs/prysm/v6/config/features" "github.com/OffchainLabs/prysm/v6/consensus-types/primitives" enginev1 "github.com/OffchainLabs/prysm/v6/proto/engine/v1" ethpb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1" @@ -24,19 +23,14 @@ type BeaconState struct { slot primitives.Slot fork *ethpb.Fork latestBlockHeader *ethpb.BeaconBlockHeader - blockRoots customtypes.BlockRoots blockRootsMultiValue *MultiValueBlockRoots - stateRoots customtypes.StateRoots stateRootsMultiValue *MultiValueStateRoots historicalRoots customtypes.HistoricalRoots eth1Data *ethpb.Eth1Data eth1DataVotes []*ethpb.Eth1Data eth1DepositIndex uint64 - validators []*ethpb.Validator validatorsMultiValue *MultiValueValidators - balances []uint64 balancesMultiValue *MultiValueBalances - randaoMixes customtypes.RandaoMixes randaoMixesMultiValue *MultiValueRandaoMixes slashings []uint64 previousEpochAttestations []*ethpb.PendingAttestation @@ -47,7 +41,6 @@ type BeaconState struct { previousJustifiedCheckpoint *ethpb.Checkpoint currentJustifiedCheckpoint *ethpb.Checkpoint finalizedCheckpoint *ethpb.Checkpoint - inactivityScores []uint64 inactivityScoresMultiValue *MultiValueInactivityScores currentSyncCommittee *ethpb.SyncCommittee nextSyncCommittee *ethpb.SyncCommittee @@ -130,28 +123,12 @@ type beaconStateMarshalable struct { } func (b *BeaconState) MarshalJSON() ([]byte, error) { - var bRoots customtypes.BlockRoots - var sRoots customtypes.StateRoots - var mixes customtypes.RandaoMixes - var balances []uint64 - var inactivityScores []uint64 - var vals []*ethpb.Validator - - if features.Get().EnableExperimentalState { - bRoots = b.blockRootsMultiValue.Value(b) - sRoots = b.stateRootsMultiValue.Value(b) - mixes = b.randaoMixesMultiValue.Value(b) - balances = b.balancesMultiValue.Value(b) - inactivityScores = b.inactivityScoresMultiValue.Value(b) - vals = b.validatorsMultiValue.Value(b) - } else { - bRoots = b.blockRoots - sRoots = b.stateRoots - mixes = b.randaoMixes - balances = b.balances - inactivityScores = b.inactivityScores - vals = b.validators - } + bRoots := b.blockRootsMultiValue.Value(b) + sRoots := b.stateRootsMultiValue.Value(b) + mixes := b.randaoMixesMultiValue.Value(b) + balances := b.balancesMultiValue.Value(b) + inactivityScores := b.inactivityScoresMultiValue.Value(b) + vals := b.validatorsMultiValue.Value(b) marshalable := &beaconStateMarshalable{ Version: b.version, diff --git a/beacon-chain/state/state-native/getters_block.go b/beacon-chain/state/state-native/getters_block.go index bfcfdbe9b7..aab46231d0 100644 --- a/beacon-chain/state/state-native/getters_block.go +++ b/beacon-chain/state/state-native/getters_block.go @@ -2,10 +2,7 @@ package state_native import ( customtypes "github.com/OffchainLabs/prysm/v6/beacon-chain/state/state-native/custom-types" - "github.com/OffchainLabs/prysm/v6/config/features" - consensus_types "github.com/OffchainLabs/prysm/v6/consensus-types" ethpb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1" - "github.com/pkg/errors" ) // LatestBlockHeader stored within the beacon state. @@ -58,13 +55,10 @@ func (b *BeaconState) BlockRoots() [][]byte { } func (b *BeaconState) blockRootsVal() customtypes.BlockRoots { - if features.Get().EnableExperimentalState { - if b.blockRootsMultiValue == nil { - return nil - } - return b.blockRootsMultiValue.Value(b) + if b.blockRootsMultiValue == nil { + return nil } - return b.blockRoots + return b.blockRootsMultiValue.Value(b) } // BlockRootAtIndex retrieves a specific block root based on an @@ -73,33 +67,12 @@ func (b *BeaconState) BlockRootAtIndex(idx uint64) ([]byte, error) { b.lock.RLock() defer b.lock.RUnlock() - if features.Get().EnableExperimentalState { - if b.blockRootsMultiValue == nil { - return []byte{}, nil - } - r, err := b.blockRootsMultiValue.At(b, idx) - if err != nil { - return nil, err - } - return r[:], nil - } - - if b.blockRoots == nil { + if b.blockRootsMultiValue == nil { return []byte{}, nil } - r, err := b.blockRootAtIndex(idx) + r, err := b.blockRootsMultiValue.At(b, idx) if err != nil { return nil, err } return r[:], nil } - -// blockRootAtIndex retrieves a specific block root based on an -// input index value. -// This assumes that a lock is already held on BeaconState. -func (b *BeaconState) blockRootAtIndex(idx uint64) ([32]byte, error) { - if uint64(len(b.blockRoots)) <= idx { - return [32]byte{}, errors.Wrapf(consensus_types.ErrOutOfBounds, "block root index %d does not exist", idx) - } - return b.blockRoots[idx], nil -} diff --git a/beacon-chain/state/state-native/getters_participation.go b/beacon-chain/state/state-native/getters_participation.go index 2e0214e24d..16f40641b5 100644 --- a/beacon-chain/state/state-native/getters_participation.go +++ b/beacon-chain/state/state-native/getters_participation.go @@ -4,7 +4,6 @@ import ( "github.com/OffchainLabs/prysm/v6/beacon-chain/core/time" customtypes "github.com/OffchainLabs/prysm/v6/beacon-chain/state/state-native/custom-types" "github.com/OffchainLabs/prysm/v6/beacon-chain/state/stateutil" - "github.com/OffchainLabs/prysm/v6/config/features" "github.com/OffchainLabs/prysm/v6/runtime/version" ) @@ -82,11 +81,7 @@ func (b *BeaconState) UnrealizedCheckpointBalances() (uint64, uint64, uint64, er return 0, 0, 0, ErrNilParticipation } - if features.Get().EnableExperimentalState { - return stateutil.UnrealizedCheckpointBalances(cp, pp, stateutil.NewValMultiValueSliceReader(b.validatorsMultiValue, b), currentEpoch) - } else { - return stateutil.UnrealizedCheckpointBalances(cp, pp, stateutil.NewValSliceReader(b.validators), currentEpoch) - } + return stateutil.UnrealizedCheckpointBalances(cp, pp, stateutil.NewValMultiValueSliceReader(b.validatorsMultiValue, b), currentEpoch) } // currentEpochParticipationVal corresponding to participation bits on the beacon chain. diff --git a/beacon-chain/state/state-native/getters_randao.go b/beacon-chain/state/state-native/getters_randao.go index 42b1586be0..29cee7c693 100644 --- a/beacon-chain/state/state-native/getters_randao.go +++ b/beacon-chain/state/state-native/getters_randao.go @@ -2,9 +2,6 @@ package state_native import ( customtypes "github.com/OffchainLabs/prysm/v6/beacon-chain/state/state-native/custom-types" - "github.com/OffchainLabs/prysm/v6/config/features" - consensus_types "github.com/OffchainLabs/prysm/v6/consensus-types" - "github.com/pkg/errors" ) // RandaoMixes of block proposers on the beacon chain. @@ -20,13 +17,10 @@ func (b *BeaconState) RandaoMixes() [][]byte { } func (b *BeaconState) randaoMixesVal() customtypes.RandaoMixes { - if features.Get().EnableExperimentalState { - if b.randaoMixesMultiValue == nil { - return nil - } - return b.randaoMixesMultiValue.Value(b) + if b.randaoMixesMultiValue == nil { + return nil } - return b.randaoMixes + return b.randaoMixesMultiValue.Value(b) } // RandaoMixAtIndex retrieves a specific block root based on an @@ -35,36 +29,14 @@ func (b *BeaconState) RandaoMixAtIndex(idx uint64) ([]byte, error) { b.lock.RLock() defer b.lock.RUnlock() - if features.Get().EnableExperimentalState { - if b.randaoMixesMultiValue == nil { - return nil, nil - } - r, err := b.randaoMixesMultiValue.At(b, idx) - if err != nil { - return nil, err - } - return r[:], nil - } - - if b.randaoMixes == nil { + if b.randaoMixesMultiValue == nil { return nil, nil } - m, err := b.randaoMixAtIndex(idx) + r, err := b.randaoMixesMultiValue.At(b, idx) if err != nil { return nil, err } - return m[:], nil -} - -// randaoMixAtIndex retrieves a specific block root based on an -// input index value. -// This assumes that a lock is already held on BeaconState. -func (b *BeaconState) randaoMixAtIndex(idx uint64) ([32]byte, error) { - if uint64(len(b.randaoMixes)) <= idx { - return [32]byte{}, errors.Wrapf(consensus_types.ErrOutOfBounds, "randao mix index %d does not exist", idx) - } - - return b.randaoMixes[idx], nil + return r[:], nil } // RandaoMixesLength returns the length of the randao mixes slice. @@ -72,14 +44,8 @@ func (b *BeaconState) RandaoMixesLength() int { b.lock.RLock() defer b.lock.RUnlock() - if features.Get().EnableExperimentalState { - if b.randaoMixesMultiValue == nil { - return 0 - } - return b.randaoMixesMultiValue.Len(b) - } - if b.randaoMixes == nil { + if b.randaoMixesMultiValue == nil { return 0 } - return len(b.randaoMixes) + return b.randaoMixesMultiValue.Len(b) } diff --git a/beacon-chain/state/state-native/getters_state.go b/beacon-chain/state/state-native/getters_state.go index ec51aa8a12..a347bc9992 100644 --- a/beacon-chain/state/state-native/getters_state.go +++ b/beacon-chain/state/state-native/getters_state.go @@ -2,8 +2,6 @@ package state_native import ( customtypes "github.com/OffchainLabs/prysm/v6/beacon-chain/state/state-native/custom-types" - "github.com/OffchainLabs/prysm/v6/config/features" - consensus_types "github.com/OffchainLabs/prysm/v6/consensus-types" ethpb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1" "github.com/OffchainLabs/prysm/v6/runtime/version" "github.com/pkg/errors" @@ -24,20 +22,14 @@ func (b *BeaconState) ToProtoUnsafe() interface{} { var bals []uint64 var inactivityScores []uint64 - if features.Get().EnableExperimentalState { - if b.balancesMultiValue != nil { - bals = b.balancesMultiValue.Value(b) - } - if b.inactivityScoresMultiValue != nil { - inactivityScores = b.inactivityScoresMultiValue.Value(b) - } - if b.validatorsMultiValue != nil { - vals = b.validatorsMultiValue.Value(b) - } - } else { - bals = b.balances - inactivityScores = b.inactivityScores - vals = b.validators + if b.balancesMultiValue != nil { + bals = b.balancesMultiValue.Value(b) + } + if b.inactivityScoresMultiValue != nil { + inactivityScores = b.inactivityScoresMultiValue.Value(b) + } + if b.validatorsMultiValue != nil { + vals = b.validatorsMultiValue.Value(b) } switch b.version { @@ -536,13 +528,10 @@ func (b *BeaconState) StateRoots() [][]byte { } func (b *BeaconState) stateRootsVal() customtypes.StateRoots { - if features.Get().EnableExperimentalState { - if b.stateRootsMultiValue == nil { - return nil - } - return b.stateRootsMultiValue.Value(b) + if b.stateRootsMultiValue == nil { + return nil } - return b.stateRoots + return b.stateRootsMultiValue.Value(b) } // StateRootAtIndex retrieves a specific state root based on an @@ -551,39 +540,16 @@ func (b *BeaconState) StateRootAtIndex(idx uint64) ([]byte, error) { b.lock.RLock() defer b.lock.RUnlock() - if features.Get().EnableExperimentalState { - if b.stateRootsMultiValue == nil { - return nil, nil - } - r, err := b.stateRootsMultiValue.At(b, idx) - if err != nil { - return nil, err - } - return r[:], nil - } - - if b.stateRoots == nil { + if b.stateRootsMultiValue == nil { return nil, nil } - r, err := b.stateRootAtIndex(idx) + r, err := b.stateRootsMultiValue.At(b, idx) if err != nil { return nil, err } return r[:], nil } -// stateRootAtIndex retrieves a specific state root based on an -// input index value. -// This assumes that a lock is already held on BeaconState. -// -// WARNING: This function does not work with the multi-value slice feature. -func (b *BeaconState) stateRootAtIndex(idx uint64) ([32]byte, error) { - if uint64(len(b.stateRoots)) <= idx { - return [32]byte{}, errors.Wrapf(consensus_types.ErrOutOfBounds, "state root index %d does not exist", idx) - } - return b.stateRoots[idx], nil -} - // ProtobufBeaconStatePhase0 transforms an input into beacon state in the form of protobuf. // Error is returned if the input is not type protobuf beacon state. func ProtobufBeaconStatePhase0(s interface{}) (*ethpb.BeaconState, error) { diff --git a/beacon-chain/state/state-native/getters_validator.go b/beacon-chain/state/state-native/getters_validator.go index 134d9e1730..3e75b92d78 100644 --- a/beacon-chain/state/state-native/getters_validator.go +++ b/beacon-chain/state/state-native/getters_validator.go @@ -2,16 +2,12 @@ package state_native import ( "github.com/OffchainLabs/prysm/v6/beacon-chain/state" - "github.com/OffchainLabs/prysm/v6/config/features" fieldparams "github.com/OffchainLabs/prysm/v6/config/fieldparams" - "github.com/OffchainLabs/prysm/v6/config/params" - consensus_types "github.com/OffchainLabs/prysm/v6/consensus-types" "github.com/OffchainLabs/prysm/v6/consensus-types/primitives" "github.com/OffchainLabs/prysm/v6/crypto/bls" "github.com/OffchainLabs/prysm/v6/encoding/bytesutil" ethpb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1" "github.com/OffchainLabs/prysm/v6/runtime/version" - "github.com/pkg/errors" ) // Validators participating in consensus on the beacon chain. @@ -32,17 +28,10 @@ func (b *BeaconState) ValidatorsReadOnly() []state.ReadOnlyValidator { func (b *BeaconState) validatorsVal() []*ethpb.Validator { var v []*ethpb.Validator - if features.Get().EnableExperimentalState { - if b.validatorsMultiValue == nil { - return nil - } - v = b.validatorsMultiValue.Value(b) - } else { - if b.validators == nil { - return nil - } - v = b.validators + if b.validatorsMultiValue == nil { + return nil } + v = b.validatorsMultiValue.Value(b) res := make([]*ethpb.Validator, len(v)) for i := 0; i < len(res); i++ { @@ -56,18 +45,10 @@ func (b *BeaconState) validatorsVal() []*ethpb.Validator { } func (b *BeaconState) validatorsReadOnlyVal() []state.ReadOnlyValidator { - var v []*ethpb.Validator - if features.Get().EnableExperimentalState { - if b.validatorsMultiValue == nil { - return nil - } - v = b.validatorsMultiValue.Value(b) - } else { - if b.validators == nil { - return nil - } - v = b.validators + if b.validatorsMultiValue == nil { + return nil } + v := b.validatorsMultiValue.Value(b) res := make([]state.ReadOnlyValidator, len(v)) var err error @@ -84,34 +65,11 @@ func (b *BeaconState) validatorsReadOnlyVal() []state.ReadOnlyValidator { return res } -// references of validators participating in consensus on the beacon chain. -// This assumes that a lock is already held on BeaconState. This does not -// copy fully and instead just copies the reference. -func (b *BeaconState) validatorsReferences() []*ethpb.Validator { - if b.validators == nil { - return nil - } - - res := make([]*ethpb.Validator, len(b.validators), len(b.validators)+int(params.BeaconConfig().MaxDeposits)) - for i := 0; i < len(res); i++ { - validator := b.validators[i] - if validator == nil { - continue - } - // copy validator reference instead. - res[i] = validator - } - return res -} - func (b *BeaconState) validatorsLen() int { - if features.Get().EnableExperimentalState { - if b.validatorsMultiValue == nil { - return 0 - } - return b.validatorsMultiValue.Len(b) + if b.validatorsMultiValue == nil { + return 0 } - return len(b.validators) + return b.validatorsMultiValue.Len(b) } // ValidatorAtIndex is the validator at the provided index. @@ -123,25 +81,14 @@ func (b *BeaconState) ValidatorAtIndex(idx primitives.ValidatorIndex) (*ethpb.Va } func (b *BeaconState) validatorAtIndex(idx primitives.ValidatorIndex) (*ethpb.Validator, error) { - if features.Get().EnableExperimentalState { - if b.validatorsMultiValue == nil { - return ðpb.Validator{}, nil - } - v, err := b.validatorsMultiValue.At(b, uint64(idx)) - if err != nil { - return nil, err - } - return ethpb.CopyValidator(v), nil - } - - if b.validators == nil { + if b.validatorsMultiValue == nil { return ðpb.Validator{}, nil } - if uint64(len(b.validators)) <= uint64(idx) { - return nil, errors.Wrapf(consensus_types.ErrOutOfBounds, "validator index %d does not exist", idx) + v, err := b.validatorsMultiValue.At(b, uint64(idx)) + if err != nil { + return nil, err } - val := b.validators[idx] - return ethpb.CopyValidator(val), nil + return ethpb.CopyValidator(v), nil } // ValidatorAtIndexReadOnly is the validator at the provided index. This method @@ -154,25 +101,14 @@ func (b *BeaconState) ValidatorAtIndexReadOnly(idx primitives.ValidatorIndex) (s } func (b *BeaconState) validatorAtIndexReadOnly(idx primitives.ValidatorIndex) (state.ReadOnlyValidator, error) { - if features.Get().EnableExperimentalState { - if b.validatorsMultiValue == nil { - return nil, state.ErrNilValidatorsInState - } - v, err := b.validatorsMultiValue.At(b, uint64(idx)) - if err != nil { - return nil, err - } - return NewValidator(v) - } - - if b.validators == nil { + if b.validatorsMultiValue == nil { return nil, state.ErrNilValidatorsInState } - if uint64(len(b.validators)) <= uint64(idx) { - return nil, errors.Wrapf(consensus_types.ErrOutOfBounds, "validator index %d does not exist", idx) + v, err := b.validatorsMultiValue.At(b, uint64(idx)) + if err != nil { + return nil, err } - val := b.validators[idx] - return NewValidator(val) + return NewValidator(v) } // ValidatorIndexByPubkey returns a given validator by its 48-byte public key. @@ -183,12 +119,7 @@ func (b *BeaconState) ValidatorIndexByPubkey(key [fieldparams.BLSPubkeyLength]by b.lock.RLock() defer b.lock.RUnlock() - var numOfVals int - if features.Get().EnableExperimentalState { - numOfVals = b.validatorsMultiValue.Len(b) - } else { - numOfVals = len(b.validators) - } + numOfVals := b.validatorsMultiValue.Len(b) idx, ok := b.valMapHandler.Get(key) if ok && primitives.ValidatorIndex(numOfVals) <= idx { @@ -203,18 +134,9 @@ func (b *BeaconState) PubkeyAtIndex(idx primitives.ValidatorIndex) [fieldparams. b.lock.RLock() defer b.lock.RUnlock() - var v *ethpb.Validator - if features.Get().EnableExperimentalState { - var err error - v, err = b.validatorsMultiValue.At(b, uint64(idx)) - if err != nil { - return [fieldparams.BLSPubkeyLength]byte{} - } - } else { - if uint64(idx) >= uint64(len(b.validators)) { - return [fieldparams.BLSPubkeyLength]byte{} - } - v = b.validators[idx] + v, err := b.validatorsMultiValue.At(b, uint64(idx)) + if err != nil { + return [fieldparams.BLSPubkeyLength]byte{} } if v == nil { @@ -231,20 +153,10 @@ func (b *BeaconState) AggregateKeyFromIndices(idxs []uint64) (bls.PublicKey, err pubKeys := make([][]byte, len(idxs)) for i, idx := range idxs { - var v *ethpb.Validator - if features.Get().EnableExperimentalState { - var err error - v, err = b.validatorsMultiValue.At(b, idx) - if err != nil { - return nil, err - } - } else { - if idx >= uint64(len(b.validators)) { - return nil, consensus_types.ErrOutOfBounds - } - v = b.validators[idx] + v, err := b.validatorsMultiValue.At(b, idx) + if err != nil { + return nil, err } - if v == nil { return nil, ErrNilWrappedValidator } @@ -261,15 +173,11 @@ func (b *BeaconState) PublicKeys() ([][fieldparams.BLSPubkeyLength]byte, error) l := b.validatorsLen() res := make([][fieldparams.BLSPubkeyLength]byte, l) for i := 0; i < l; i++ { - if features.Get().EnableExperimentalState { - val, err := b.validatorsMultiValue.At(b, uint64(i)) - if err != nil { - return nil, err - } - copy(res[i][:], val.PublicKey) - } else { - copy(res[i][:], b.validators[i].PublicKey) + val, err := b.validatorsMultiValue.At(b, uint64(i)) + if err != nil { + return nil, err } + copy(res[i][:], val.PublicKey) } return res, nil } @@ -289,30 +197,6 @@ func (b *BeaconState) ReadFromEveryValidator(f func(idx int, val state.ReadOnlyV b.lock.RLock() defer b.lock.RUnlock() - if features.Get().EnableExperimentalState { - return b.readFromEveryValidatorMVSlice(f) - } - - if b.validators == nil { - return state.ErrNilValidatorsInState - } - - validators := b.validators - - for i, v := range validators { - v, err := NewValidator(v) - if err != nil { - return err - } - if err = f(i, v); err != nil { - return err - } - } - return nil -} - -// WARNING: This function works only for the multi-value slice feature. -func (b *BeaconState) readFromEveryValidatorMVSlice(f func(idx int, val state.ReadOnlyValidator) error) error { if b.validatorsMultiValue == nil { return state.ErrNilValidatorsInState } @@ -342,18 +226,10 @@ func (b *BeaconState) Balances() []uint64 { } func (b *BeaconState) balancesVal() []uint64 { - if features.Get().EnableExperimentalState { - if b.balancesMultiValue == nil { - return nil - } - return b.balancesMultiValue.Value(b) - } - if b.balances == nil { + if b.balancesMultiValue == nil { return nil } - res := make([]uint64, len(b.balances)) - copy(res, b.balances) - return res + return b.balancesMultiValue.Value(b) } // BalanceAtIndex of validator with the provided index. @@ -365,19 +241,10 @@ func (b *BeaconState) BalanceAtIndex(idx primitives.ValidatorIndex) (uint64, err } func (b *BeaconState) balanceAtIndex(idx primitives.ValidatorIndex) (uint64, error) { - if features.Get().EnableExperimentalState { - if b.balancesMultiValue == nil { - return 0, nil - } - return b.balancesMultiValue.At(b, uint64(idx)) - } - if b.balances == nil { + if b.balancesMultiValue == nil { return 0, nil } - if uint64(len(b.balances)) <= uint64(idx) { - return 0, errors.Wrapf(consensus_types.ErrOutOfBounds, "balance index %d does not exist", idx) - } - return b.balances[idx], nil + return b.balancesMultiValue.At(b, uint64(idx)) } // BalancesLength returns the length of the balances slice. @@ -385,13 +252,10 @@ func (b *BeaconState) BalancesLength() int { b.lock.RLock() defer b.lock.RUnlock() - if features.Get().EnableExperimentalState { - if b.balancesMultiValue == nil { - return 0 - } - return b.balancesMultiValue.Len(b) + if b.balancesMultiValue == nil { + return 0 } - return len(b.balances) + return b.balancesMultiValue.Len(b) } // Slashings of validators on the beacon chain. @@ -431,18 +295,10 @@ func (b *BeaconState) InactivityScores() ([]uint64, error) { } func (b *BeaconState) inactivityScoresVal() []uint64 { - if features.Get().EnableExperimentalState { - if b.inactivityScoresMultiValue == nil { - return nil - } - return b.inactivityScoresMultiValue.Value(b) - } - if b.inactivityScores == nil { + if b.inactivityScoresMultiValue == nil { return nil } - res := make([]uint64, len(b.inactivityScores)) - copy(res, b.inactivityScores) - return res + return b.inactivityScoresMultiValue.Value(b) } // PendingBalanceToWithdraw returns the sum of all pending withdrawals for the given validator. diff --git a/beacon-chain/state/state-native/mvslice_fuzz_test.go b/beacon-chain/state/state-native/mvslice_fuzz_test.go index f4237e3a76..d0a466b7ca 100644 --- a/beacon-chain/state/state-native/mvslice_fuzz_test.go +++ b/beacon-chain/state/state-native/mvslice_fuzz_test.go @@ -3,18 +3,12 @@ package state_native import ( "testing" - "github.com/OffchainLabs/prysm/v6/config/features" "github.com/OffchainLabs/prysm/v6/consensus-types/primitives" ethpb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1" "github.com/OffchainLabs/prysm/v6/testing/require" ) func FuzzMultiValueBalances(f *testing.F) { - resetFn := features.InitWithReset(&features.Flags{ - EnableExperimentalState: true, - }) - defer resetFn() - bals := make([]uint64, 65536) firstState, err := InitializeFromProtoPhase0(ðpb.BeaconState{Balances: bals}) require.NoError(f, err) diff --git a/beacon-chain/state/state-native/references_test.go b/beacon-chain/state/state-native/references_test.go index f09681bf89..67b9b406c3 100644 --- a/beacon-chain/state/state-native/references_test.go +++ b/beacon-chain/state/state-native/references_test.go @@ -8,7 +8,6 @@ import ( "github.com/OffchainLabs/prysm/v6/beacon-chain/state" "github.com/OffchainLabs/prysm/v6/beacon-chain/state/state-native/types" - "github.com/OffchainLabs/prysm/v6/config/features" "github.com/OffchainLabs/prysm/v6/encoding/bytesutil" ethpb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1" "github.com/OffchainLabs/prysm/v6/testing/assert" @@ -17,663 +16,358 @@ import ( ) func TestStateReferenceSharing_Finalizer_Phase0(t *testing.T) { - // This test showcases the logic on the RandaoMixes field with the GC finalizer. + // This test showcases the logic on the Slashings field with the GC finalizer. - s, err := InitializeFromProtoUnsafePhase0(ðpb.BeaconState{RandaoMixes: [][]byte{[]byte("foo")}}) + s, err := InitializeFromProtoUnsafePhase0(ðpb.BeaconState{Slashings: []uint64{10, 30, 40}}) require.NoError(t, err) a, ok := s.(*BeaconState) require.Equal(t, true, ok) - assert.Equal(t, uint(1), a.sharedFieldReferences[types.RandaoMixes].Refs(), "Expected a single reference for RANDAO mixes") + assert.Equal(t, uint(1), a.sharedFieldReferences[types.Slashings].Refs(), "Expected a single reference for RANDAO mixes") func() { // Create object in a different scope for GC b := a.Copy() - assert.Equal(t, uint(2), a.sharedFieldReferences[types.RandaoMixes].Refs(), "Expected 2 references to RANDAO mixes") + assert.Equal(t, uint(2), a.sharedFieldReferences[types.Slashings].Refs(), "Expected 2 references to RANDAO mixes") _ = b }() runtime.GC() // Should run finalizer on object b - assert.Equal(t, uint(1), a.sharedFieldReferences[types.RandaoMixes].Refs(), "Expected 1 shared reference to RANDAO mixes!") + assert.Equal(t, uint(1), a.sharedFieldReferences[types.Slashings].Refs(), "Expected 1 shared reference to RANDAO mixes!") copied := a.Copy() b, ok := copied.(*BeaconState) require.Equal(t, true, ok) - assert.Equal(t, uint(2), b.sharedFieldReferences[types.RandaoMixes].Refs(), "Expected 2 shared references to RANDAO mixes") - require.NoError(t, b.UpdateRandaoMixesAtIndex(0, bytesutil.ToBytes32([]byte("bar")))) - if b.sharedFieldReferences[types.RandaoMixes].Refs() != 1 || a.sharedFieldReferences[types.RandaoMixes].Refs() != 1 { - t.Error("Expected 1 shared reference to RANDAO mix for both a and b") + assert.Equal(t, uint(2), b.sharedFieldReferences[types.Slashings].Refs(), "Expected 2 shared references to RANDAO mixes") + require.NoError(t, b.UpdateSlashingsAtIndex(0, 100)) + if b.sharedFieldReferences[types.Slashings].Refs() != 1 || a.sharedFieldReferences[types.Slashings].Refs() != 1 { + t.Error("Expected 1 shared reference to Slashings for both a and b") } } func TestStateReferenceSharing_Finalizer_Altair(t *testing.T) { - // This test showcases the logic on the RandaoMixes field with the GC finalizer. + // This test showcases the logic on the Slashings field with the GC finalizer. - s, err := InitializeFromProtoUnsafeAltair(ðpb.BeaconStateAltair{RandaoMixes: [][]byte{[]byte("foo")}}) + s, err := InitializeFromProtoUnsafeAltair(ðpb.BeaconStateAltair{Slashings: []uint64{10, 30, 40}}) require.NoError(t, err) a, ok := s.(*BeaconState) require.Equal(t, true, ok) - assert.Equal(t, uint(1), a.sharedFieldReferences[types.RandaoMixes].Refs(), "Expected a single reference for RANDAO mixes") + assert.Equal(t, uint(1), a.sharedFieldReferences[types.Slashings].Refs(), "Expected a single reference for RANDAO mixes") func() { // Create object in a different scope for GC b := a.Copy() - assert.Equal(t, uint(2), a.sharedFieldReferences[types.RandaoMixes].Refs(), "Expected 2 references to RANDAO mixes") + assert.Equal(t, uint(2), a.sharedFieldReferences[types.Slashings].Refs(), "Expected 2 references to RANDAO mixes") _ = b }() runtime.GC() // Should run finalizer on object b - assert.Equal(t, uint(1), a.sharedFieldReferences[types.RandaoMixes].Refs(), "Expected 1 shared reference to RANDAO mixes!") + assert.Equal(t, uint(1), a.sharedFieldReferences[types.Slashings].Refs(), "Expected 1 shared reference to RANDAO mixes!") copied := a.Copy() b, ok := copied.(*BeaconState) require.Equal(t, true, ok) - assert.Equal(t, uint(2), b.sharedFieldReferences[types.RandaoMixes].Refs(), "Expected 2 shared references to RANDAO mixes") - require.NoError(t, b.UpdateRandaoMixesAtIndex(0, bytesutil.ToBytes32([]byte("bar")))) - if b.sharedFieldReferences[types.RandaoMixes].Refs() != 1 || a.sharedFieldReferences[types.RandaoMixes].Refs() != 1 { - t.Error("Expected 1 shared reference to RANDAO mix for both a and b") + assert.Equal(t, uint(2), b.sharedFieldReferences[types.Slashings].Refs(), "Expected 2 shared references to RANDAO mixes") + require.NoError(t, b.UpdateSlashingsAtIndex(0, 100)) + if b.sharedFieldReferences[types.Slashings].Refs() != 1 || a.sharedFieldReferences[types.Slashings].Refs() != 1 { + t.Error("Expected 1 shared reference to Slashings for both a and b") } } func TestStateReferenceSharing_Finalizer_Bellatrix(t *testing.T) { - // This test showcases the logic on the RandaoMixes field with the GC finalizer. + // This test showcases the logic on the Slashings field with the GC finalizer. - s, err := InitializeFromProtoUnsafeBellatrix(ðpb.BeaconStateBellatrix{RandaoMixes: [][]byte{[]byte("foo")}}) + s, err := InitializeFromProtoUnsafeBellatrix(ðpb.BeaconStateBellatrix{Slashings: []uint64{10, 30, 40}}) require.NoError(t, err) a, ok := s.(*BeaconState) require.Equal(t, true, ok) - assert.Equal(t, uint(1), a.sharedFieldReferences[types.RandaoMixes].Refs(), "Expected a single reference for RANDAO mixes") + assert.Equal(t, uint(1), a.sharedFieldReferences[types.Slashings].Refs(), "Expected a single reference for RANDAO mixes") func() { // Create object in a different scope for GC b := a.Copy() - assert.Equal(t, uint(2), a.sharedFieldReferences[types.RandaoMixes].Refs(), "Expected 2 references to RANDAO mixes") + assert.Equal(t, uint(2), a.sharedFieldReferences[types.Slashings].Refs(), "Expected 2 references to RANDAO mixes") _ = b }() runtime.GC() // Should run finalizer on object b - assert.Equal(t, uint(1), a.sharedFieldReferences[types.RandaoMixes].Refs(), "Expected 1 shared reference to RANDAO mixes!") + assert.Equal(t, uint(1), a.sharedFieldReferences[types.Slashings].Refs(), "Expected 1 shared reference to RANDAO mixes!") copied := a.Copy() b, ok := copied.(*BeaconState) require.Equal(t, true, ok) - assert.Equal(t, uint(2), b.sharedFieldReferences[types.RandaoMixes].Refs(), "Expected 2 shared references to RANDAO mixes") - require.NoError(t, b.UpdateRandaoMixesAtIndex(0, bytesutil.ToBytes32([]byte("bar")))) - if b.sharedFieldReferences[types.RandaoMixes].Refs() != 1 || a.sharedFieldReferences[types.RandaoMixes].Refs() != 1 { - t.Error("Expected 1 shared reference to RANDAO mix for both a and b") + assert.Equal(t, uint(2), b.sharedFieldReferences[types.Slashings].Refs(), "Expected 2 shared references to RANDAO mixes") + require.NoError(t, b.UpdateSlashingsAtIndex(0, 100)) + if b.sharedFieldReferences[types.Slashings].Refs() != 1 || a.sharedFieldReferences[types.Slashings].Refs() != 1 { + t.Error("Expected 1 shared reference to Slashings for both a and b") } } func TestStateReferenceSharing_Finalizer_Capella(t *testing.T) { - // This test showcases the logic on the RandaoMixes field with the GC finalizer. + // This test showcases the logic on the Slashings field with the GC finalizer. - s, err := InitializeFromProtoUnsafeCapella(ðpb.BeaconStateCapella{RandaoMixes: [][]byte{[]byte("foo")}}) + s, err := InitializeFromProtoUnsafeCapella(ðpb.BeaconStateCapella{Slashings: []uint64{10, 30, 40}}) require.NoError(t, err) a, ok := s.(*BeaconState) require.Equal(t, true, ok) - assert.Equal(t, uint(1), a.sharedFieldReferences[types.RandaoMixes].Refs(), "Expected a single reference for RANDAO mixes") + assert.Equal(t, uint(1), a.sharedFieldReferences[types.Slashings].Refs(), "Expected a single reference for RANDAO mixes") func() { // Create object in a different scope for GC b := a.Copy() - assert.Equal(t, uint(2), a.sharedFieldReferences[types.RandaoMixes].Refs(), "Expected 2 references to RANDAO mixes") + assert.Equal(t, uint(2), a.sharedFieldReferences[types.Slashings].Refs(), "Expected 2 references to RANDAO mixes") _ = b }() runtime.GC() // Should run finalizer on object b - assert.Equal(t, uint(1), a.sharedFieldReferences[types.RandaoMixes].Refs(), "Expected 1 shared reference to RANDAO mixes!") + assert.Equal(t, uint(1), a.sharedFieldReferences[types.Slashings].Refs(), "Expected 1 shared reference to RANDAO mixes!") copied := a.Copy() b, ok := copied.(*BeaconState) require.Equal(t, true, ok) - assert.Equal(t, uint(2), b.sharedFieldReferences[types.RandaoMixes].Refs(), "Expected 2 shared references to RANDAO mixes") - require.NoError(t, b.UpdateRandaoMixesAtIndex(0, bytesutil.ToBytes32([]byte("bar")))) - if b.sharedFieldReferences[types.RandaoMixes].Refs() != 1 || a.sharedFieldReferences[types.RandaoMixes].Refs() != 1 { - t.Error("Expected 1 shared reference to RANDAO mix for both a and b") + assert.Equal(t, uint(2), b.sharedFieldReferences[types.Slashings].Refs(), "Expected 2 shared references to RANDAO mixes") + require.NoError(t, b.UpdateSlashingsAtIndex(0, 100)) + if b.sharedFieldReferences[types.Slashings].Refs() != 1 || a.sharedFieldReferences[types.Slashings].Refs() != 1 { + t.Error("Expected 1 shared reference to Slashings for both a and b") } } func TestStateReferenceSharing_Finalizer_Deneb(t *testing.T) { - // This test showcases the logic on the RandaoMixes field with the GC finalizer. + // This test showcases the logic on the Slashings field with the GC finalizer. - s, err := InitializeFromProtoUnsafeDeneb(ðpb.BeaconStateDeneb{RandaoMixes: [][]byte{[]byte("foo")}}) + s, err := InitializeFromProtoUnsafeDeneb(ðpb.BeaconStateDeneb{Slashings: []uint64{10, 30, 40}}) require.NoError(t, err) a, ok := s.(*BeaconState) require.Equal(t, true, ok) - assert.Equal(t, uint(1), a.sharedFieldReferences[types.RandaoMixes].Refs(), "Expected a single reference for RANDAO mixes") + assert.Equal(t, uint(1), a.sharedFieldReferences[types.Slashings].Refs(), "Expected a single reference for RANDAO mixes") func() { // Create object in a different scope for GC b := a.Copy() - assert.Equal(t, uint(2), a.sharedFieldReferences[types.RandaoMixes].Refs(), "Expected 2 references to RANDAO mixes") + assert.Equal(t, uint(2), a.sharedFieldReferences[types.Slashings].Refs(), "Expected 2 references to RANDAO mixes") _ = b }() runtime.GC() // Should run finalizer on object b - assert.Equal(t, uint(1), a.sharedFieldReferences[types.RandaoMixes].Refs(), "Expected 1 shared reference to RANDAO mixes!") + assert.Equal(t, uint(1), a.sharedFieldReferences[types.Slashings].Refs(), "Expected 1 shared reference to RANDAO mixes!") copied := a.Copy() b, ok := copied.(*BeaconState) require.Equal(t, true, ok) - assert.Equal(t, uint(2), b.sharedFieldReferences[types.RandaoMixes].Refs(), "Expected 2 shared references to RANDAO mixes") - require.NoError(t, b.UpdateRandaoMixesAtIndex(0, bytesutil.ToBytes32([]byte("bar")))) - if b.sharedFieldReferences[types.RandaoMixes].Refs() != 1 || a.sharedFieldReferences[types.RandaoMixes].Refs() != 1 { - t.Error("Expected 1 shared reference to RANDAO mix for both a and b") + assert.Equal(t, uint(2), b.sharedFieldReferences[types.Slashings].Refs(), "Expected 2 shared references to RANDAO mixes") + require.NoError(t, b.UpdateSlashingsAtIndex(0, 100)) + if b.sharedFieldReferences[types.Slashings].Refs() != 1 || a.sharedFieldReferences[types.Slashings].Refs() != 1 { + t.Error("Expected 1 shared reference to Slashings for both a and b") } } -func TestStateReferenceCopy_NoUnexpectedRootsMutation_Phase0(t *testing.T) { - root1, root2 := bytesutil.ToBytes32([]byte("foo")), bytesutil.ToBytes32([]byte("bar")) +func TestStateReferenceCopy_NoUnexpectedSlashingsMutation_Phase0(t *testing.T) { + val1, val2 := uint64(10), uint64(20) s, err := InitializeFromProtoUnsafePhase0(ðpb.BeaconState{ - BlockRoots: [][]byte{ - root1[:], - }, - StateRoots: [][]byte{ - root1[:], - }, + Slashings: []uint64{val1}, }) require.NoError(t, err) a, ok := s.(*BeaconState) require.Equal(t, true, ok) require.NoError(t, err) - assertRefCount(t, a, types.BlockRoots, 1) - assertRefCount(t, a, types.StateRoots, 1) + assertRefCount(t, a, types.Slashings, 1) // Copy, increases reference count. copied := a.Copy() b, ok := copied.(*BeaconState) require.Equal(t, true, ok) - assertRefCount(t, a, types.BlockRoots, 2) - assertRefCount(t, a, types.StateRoots, 2) - assertRefCount(t, b, types.BlockRoots, 2) - assertRefCount(t, b, types.StateRoots, 2) + assertRefCount(t, a, types.Slashings, 2) + assertRefCount(t, b, types.Slashings, 2) // Assert shared state. - blockRootsA := a.BlockRoots() - stateRootsA := a.StateRoots() - blockRootsB := b.BlockRoots() - stateRootsB := b.StateRoots() - assertValFound(t, blockRootsA, root1[:]) - assertValFound(t, blockRootsB, root1[:]) - assertValFound(t, stateRootsA, root1[:]) - assertValFound(t, stateRootsB, root1[:]) + slashingsA := a.Slashings() + slashingsB := b.Slashings() + assertValFound(t, slashingsA, val1) + assertValFound(t, slashingsB, val1) // Mutator should only affect calling state: a. - require.NoError(t, a.UpdateBlockRootAtIndex(0, root2)) - require.NoError(t, a.UpdateStateRootAtIndex(0, root2)) + require.NoError(t, a.UpdateSlashingsAtIndex(0, val2)) // Assert no shared state mutation occurred only on state a (copy on write). - assertValNotFound(t, a.BlockRoots(), root1[:]) - assertValNotFound(t, a.StateRoots(), root1[:]) - assertValFound(t, a.BlockRoots(), root2[:]) - assertValFound(t, a.StateRoots(), root2[:]) - assertValFound(t, b.BlockRoots(), root1[:]) - assertValFound(t, b.StateRoots(), root1[:]) - assert.DeepEqual(t, root2[:], a.BlockRoots()[0], "Expected mutation not found") - assert.DeepEqual(t, root2[:], a.StateRoots()[0], "Expected mutation not found") - assert.DeepEqual(t, root1[:], blockRootsB[0], "Unexpected mutation found") - assert.DeepEqual(t, root1[:], stateRootsB[0], "Unexpected mutation found") + assertValFound(t, a.Slashings(), val2) + assertValNotFound(t, a.Slashings(), val1) + assertValFound(t, b.Slashings(), val1) + assertValNotFound(t, b.Slashings(), val2) + assertValFound(t, slashingsB, val1) + assertValNotFound(t, slashingsB, val2) + assert.DeepEqual(t, val2, a.Slashings()[0], "Expected mutation not found") + assert.DeepEqual(t, val1, slashingsB[0], "Unexpected mutation found") // Copy on write happened, reference counters are reset. - assertRefCount(t, a, types.BlockRoots, 1) - assertRefCount(t, a, types.StateRoots, 1) - assertRefCount(t, b, types.BlockRoots, 1) - assertRefCount(t, b, types.StateRoots, 1) + assertRefCount(t, a, types.Slashings, 1) + assertRefCount(t, b, types.Slashings, 1) } -func TestStateReferenceCopy_NoUnexpectedRootsMutation_Altair(t *testing.T) { - root1, root2 := bytesutil.ToBytes32([]byte("foo")), bytesutil.ToBytes32([]byte("bar")) +func TestStateReferenceCopy_NoUnexpectedSlashingMutation_Altair(t *testing.T) { + val1, val2 := uint64(10), uint64(20) s, err := InitializeFromProtoUnsafeAltair(ðpb.BeaconStateAltair{ - BlockRoots: [][]byte{ - root1[:], - }, - StateRoots: [][]byte{ - root1[:], - }, + Slashings: []uint64{val1}, }) require.NoError(t, err) a, ok := s.(*BeaconState) require.Equal(t, true, ok) require.NoError(t, err) - assertRefCount(t, a, types.BlockRoots, 1) - assertRefCount(t, a, types.StateRoots, 1) + assertRefCount(t, a, types.Slashings, 1) // Copy, increases reference count. copied := a.Copy() b, ok := copied.(*BeaconState) require.Equal(t, true, ok) - assertRefCount(t, a, types.BlockRoots, 2) - assertRefCount(t, a, types.StateRoots, 2) - assertRefCount(t, b, types.BlockRoots, 2) - assertRefCount(t, b, types.StateRoots, 2) + assertRefCount(t, a, types.Slashings, 2) + assertRefCount(t, b, types.Slashings, 2) // Assert shared state. - blockRootsA := a.BlockRoots() - stateRootsA := a.StateRoots() - blockRootsB := b.BlockRoots() - stateRootsB := b.StateRoots() - assertValFound(t, blockRootsA, root1[:]) - assertValFound(t, blockRootsB, root1[:]) - assertValFound(t, stateRootsA, root1[:]) - assertValFound(t, stateRootsB, root1[:]) + slashingsA := a.Slashings() + slashingsB := b.Slashings() + assertValFound(t, slashingsA, val1) + assertValFound(t, slashingsB, val1) // Mutator should only affect calling state: a. - require.NoError(t, a.UpdateBlockRootAtIndex(0, root2)) - require.NoError(t, a.UpdateStateRootAtIndex(0, root2)) + require.NoError(t, a.UpdateSlashingsAtIndex(0, val2)) // Assert no shared state mutation occurred only on state a (copy on write). - assertValNotFound(t, a.BlockRoots(), root1[:]) - assertValNotFound(t, a.StateRoots(), root1[:]) - assertValFound(t, a.BlockRoots(), root2[:]) - assertValFound(t, a.StateRoots(), root2[:]) - assertValFound(t, b.BlockRoots(), root1[:]) - assertValFound(t, b.StateRoots(), root1[:]) - assert.DeepEqual(t, root2[:], a.BlockRoots()[0], "Expected mutation not found") - assert.DeepEqual(t, root2[:], a.StateRoots()[0], "Expected mutation not found") - assert.DeepEqual(t, root1[:], blockRootsB[0], "Unexpected mutation found") - assert.DeepEqual(t, root1[:], stateRootsB[0], "Unexpected mutation found") + assertValFound(t, a.Slashings(), val2) + assertValNotFound(t, a.Slashings(), val1) + assertValFound(t, b.Slashings(), val1) + assertValNotFound(t, b.Slashings(), val2) + assertValFound(t, slashingsB, val1) + assertValNotFound(t, slashingsB, val2) + assert.DeepEqual(t, val2, a.Slashings()[0], "Expected mutation not found") + assert.DeepEqual(t, val1, slashingsB[0], "Unexpected mutation found") // Copy on write happened, reference counters are reset. - assertRefCount(t, a, types.BlockRoots, 1) - assertRefCount(t, a, types.StateRoots, 1) - assertRefCount(t, b, types.BlockRoots, 1) - assertRefCount(t, b, types.StateRoots, 1) + assertRefCount(t, a, types.Slashings, 1) + assertRefCount(t, b, types.Slashings, 1) } -func TestStateReferenceCopy_NoUnexpectedRootsMutation_Bellatrix(t *testing.T) { - root1, root2 := bytesutil.ToBytes32([]byte("foo")), bytesutil.ToBytes32([]byte("bar")) +func TestStateReferenceCopy_NoUnexpectedSlashingMutation_Bellatrix(t *testing.T) { + val1, val2 := uint64(10), uint64(20) s, err := InitializeFromProtoUnsafeBellatrix(ðpb.BeaconStateBellatrix{ - BlockRoots: [][]byte{ - root1[:], - }, - StateRoots: [][]byte{ - root1[:], - }, + Slashings: []uint64{val1}, }) require.NoError(t, err) a, ok := s.(*BeaconState) require.Equal(t, true, ok) require.NoError(t, err) - assertRefCount(t, a, types.BlockRoots, 1) - assertRefCount(t, a, types.StateRoots, 1) + assertRefCount(t, a, types.Slashings, 1) // Copy, increases reference count. copied := a.Copy() b, ok := copied.(*BeaconState) require.Equal(t, true, ok) - assertRefCount(t, a, types.BlockRoots, 2) - assertRefCount(t, a, types.StateRoots, 2) - assertRefCount(t, b, types.BlockRoots, 2) - assertRefCount(t, b, types.StateRoots, 2) + assertRefCount(t, a, types.Slashings, 2) + assertRefCount(t, b, types.Slashings, 2) // Assert shared state. - blockRootsA := a.BlockRoots() - stateRootsA := a.StateRoots() - blockRootsB := b.BlockRoots() - stateRootsB := b.StateRoots() - assertValFound(t, blockRootsA, root1[:]) - assertValFound(t, blockRootsB, root1[:]) - assertValFound(t, stateRootsA, root1[:]) - assertValFound(t, stateRootsB, root1[:]) + slashingsA := a.Slashings() + slashingsB := b.Slashings() + assertValFound(t, slashingsA, val1) + assertValFound(t, slashingsB, val1) // Mutator should only affect calling state: a. - require.NoError(t, a.UpdateBlockRootAtIndex(0, root2)) - require.NoError(t, a.UpdateStateRootAtIndex(0, root2)) + require.NoError(t, a.UpdateSlashingsAtIndex(0, val2)) // Assert no shared state mutation occurred only on state a (copy on write). - assertValNotFound(t, a.BlockRoots(), root1[:]) - assertValNotFound(t, a.StateRoots(), root1[:]) - assertValFound(t, a.BlockRoots(), root2[:]) - assertValFound(t, a.StateRoots(), root2[:]) - assertValFound(t, b.BlockRoots(), root1[:]) - assertValFound(t, b.StateRoots(), root1[:]) - assert.DeepEqual(t, root2[:], a.BlockRoots()[0], "Expected mutation not found") - assert.DeepEqual(t, root2[:], a.StateRoots()[0], "Expected mutation not found") - assert.DeepEqual(t, root1[:], blockRootsB[0], "Unexpected mutation found") - assert.DeepEqual(t, root1[:], stateRootsB[0], "Unexpected mutation found") + assertValFound(t, a.Slashings(), val2) + assertValNotFound(t, a.Slashings(), val1) + assertValFound(t, b.Slashings(), val1) + assertValNotFound(t, b.Slashings(), val2) + assertValFound(t, slashingsB, val1) + assertValNotFound(t, slashingsB, val2) + assert.DeepEqual(t, val2, a.Slashings()[0], "Expected mutation not found") + assert.DeepEqual(t, val1, slashingsB[0], "Unexpected mutation found") // Copy on write happened, reference counters are reset. - assertRefCount(t, a, types.BlockRoots, 1) - assertRefCount(t, a, types.StateRoots, 1) - assertRefCount(t, b, types.BlockRoots, 1) - assertRefCount(t, b, types.StateRoots, 1) + assertRefCount(t, a, types.Slashings, 1) + assertRefCount(t, b, types.Slashings, 1) } -func TestStateReferenceCopy_NoUnexpectedRootsMutation_Capella(t *testing.T) { - root1, root2 := bytesutil.ToBytes32([]byte("foo")), bytesutil.ToBytes32([]byte("bar")) +func TestStateReferenceCopy_NoUnexpectedSlashingMutation_Capella(t *testing.T) { + val1, val2 := uint64(10), uint64(20) s, err := InitializeFromProtoUnsafeCapella(ðpb.BeaconStateCapella{ - BlockRoots: [][]byte{ - root1[:], - }, - StateRoots: [][]byte{ - root1[:], - }, + Slashings: []uint64{val1}, }) require.NoError(t, err) a, ok := s.(*BeaconState) require.Equal(t, true, ok) require.NoError(t, err) - assertRefCount(t, a, types.BlockRoots, 1) - assertRefCount(t, a, types.StateRoots, 1) + assertRefCount(t, a, types.Slashings, 1) // Copy, increases reference count. copied := a.Copy() b, ok := copied.(*BeaconState) require.Equal(t, true, ok) - assertRefCount(t, a, types.BlockRoots, 2) - assertRefCount(t, a, types.StateRoots, 2) - assertRefCount(t, b, types.BlockRoots, 2) - assertRefCount(t, b, types.StateRoots, 2) + assertRefCount(t, a, types.Slashings, 2) + assertRefCount(t, b, types.Slashings, 2) // Assert shared state. - blockRootsA := a.BlockRoots() - stateRootsA := a.StateRoots() - blockRootsB := b.BlockRoots() - stateRootsB := b.StateRoots() - assertValFound(t, blockRootsA, root1[:]) - assertValFound(t, blockRootsB, root1[:]) - assertValFound(t, stateRootsA, root1[:]) - assertValFound(t, stateRootsB, root1[:]) + slashingsA := a.Slashings() + slashingsB := b.Slashings() + assertValFound(t, slashingsA, val1) + assertValFound(t, slashingsB, val1) // Mutator should only affect calling state: a. - require.NoError(t, a.UpdateBlockRootAtIndex(0, root2)) - require.NoError(t, a.UpdateStateRootAtIndex(0, root2)) + require.NoError(t, a.UpdateSlashingsAtIndex(0, val2)) // Assert no shared state mutation occurred only on state a (copy on write). - assertValNotFound(t, a.BlockRoots(), root1[:]) - assertValNotFound(t, a.StateRoots(), root1[:]) - assertValFound(t, a.BlockRoots(), root2[:]) - assertValFound(t, a.StateRoots(), root2[:]) - assertValFound(t, b.BlockRoots(), root1[:]) - assertValFound(t, b.StateRoots(), root1[:]) - assert.DeepEqual(t, root2[:], a.BlockRoots()[0], "Expected mutation not found") - assert.DeepEqual(t, root2[:], a.StateRoots()[0], "Expected mutation not found") - assert.DeepEqual(t, root1[:], blockRootsB[0], "Unexpected mutation found") - assert.DeepEqual(t, root1[:], stateRootsB[0], "Unexpected mutation found") + assertValFound(t, a.Slashings(), val2) + assertValNotFound(t, a.Slashings(), val1) + assertValFound(t, b.Slashings(), val1) + assertValNotFound(t, b.Slashings(), val2) + assertValFound(t, slashingsB, val1) + assertValNotFound(t, slashingsB, val2) + assert.DeepEqual(t, val2, a.Slashings()[0], "Expected mutation not found") + assert.DeepEqual(t, val1, slashingsB[0], "Unexpected mutation found") // Copy on write happened, reference counters are reset. - assertRefCount(t, a, types.BlockRoots, 1) - assertRefCount(t, a, types.StateRoots, 1) - assertRefCount(t, b, types.BlockRoots, 1) - assertRefCount(t, b, types.StateRoots, 1) + assertRefCount(t, a, types.Slashings, 1) + assertRefCount(t, b, types.Slashings, 1) } -func TestStateReferenceCopy_NoUnexpectedRootsMutation_Deneb(t *testing.T) { - root1, root2 := bytesutil.ToBytes32([]byte("foo")), bytesutil.ToBytes32([]byte("bar")) +func TestStateReferenceCopy_NoUnexpectedSlashingMutation_Deneb(t *testing.T) { + val1, val2 := uint64(10), uint64(20) s, err := InitializeFromProtoUnsafeDeneb(ðpb.BeaconStateDeneb{ - BlockRoots: [][]byte{ - root1[:], - }, - StateRoots: [][]byte{ - root1[:], - }, + Slashings: []uint64{val1}, }) require.NoError(t, err) a, ok := s.(*BeaconState) require.Equal(t, true, ok) require.NoError(t, err) - assertRefCount(t, a, types.BlockRoots, 1) - assertRefCount(t, a, types.StateRoots, 1) + assertRefCount(t, a, types.Slashings, 1) // Copy, increases reference count. copied := a.Copy() b, ok := copied.(*BeaconState) require.Equal(t, true, ok) - assertRefCount(t, a, types.BlockRoots, 2) - assertRefCount(t, a, types.StateRoots, 2) - assertRefCount(t, b, types.BlockRoots, 2) - assertRefCount(t, b, types.StateRoots, 2) + assertRefCount(t, a, types.Slashings, 2) + assertRefCount(t, b, types.Slashings, 2) // Assert shared state. - blockRootsA := a.BlockRoots() - stateRootsA := a.StateRoots() - blockRootsB := b.BlockRoots() - stateRootsB := b.StateRoots() - assertValFound(t, blockRootsA, root1[:]) - assertValFound(t, blockRootsB, root1[:]) - assertValFound(t, stateRootsA, root1[:]) - assertValFound(t, stateRootsB, root1[:]) + slashingsA := a.Slashings() + slashingsB := b.Slashings() + assertValFound(t, slashingsA, val1) + assertValFound(t, slashingsB, val1) // Mutator should only affect calling state: a. - require.NoError(t, a.UpdateBlockRootAtIndex(0, root2)) - require.NoError(t, a.UpdateStateRootAtIndex(0, root2)) + require.NoError(t, a.UpdateSlashingsAtIndex(0, val2)) // Assert no shared state mutation occurred only on state a (copy on write). - assertValNotFound(t, a.BlockRoots(), root1[:]) - assertValNotFound(t, a.StateRoots(), root1[:]) - assertValFound(t, a.BlockRoots(), root2[:]) - assertValFound(t, a.StateRoots(), root2[:]) - assertValFound(t, b.BlockRoots(), root1[:]) - assertValFound(t, b.StateRoots(), root1[:]) - assert.DeepEqual(t, root2[:], a.BlockRoots()[0], "Expected mutation not found") - assert.DeepEqual(t, root2[:], a.StateRoots()[0], "Expected mutation not found") - assert.DeepEqual(t, root1[:], blockRootsB[0], "Unexpected mutation found") - assert.DeepEqual(t, root1[:], stateRootsB[0], "Unexpected mutation found") + assertValFound(t, a.Slashings(), val2) + assertValNotFound(t, a.Slashings(), val1) + assertValFound(t, b.Slashings(), val1) + assertValNotFound(t, b.Slashings(), val2) + assertValFound(t, slashingsB, val1) + assertValNotFound(t, slashingsB, val2) + assert.DeepEqual(t, val2, a.Slashings()[0], "Expected mutation not found") + assert.DeepEqual(t, val1, slashingsB[0], "Unexpected mutation found") // Copy on write happened, reference counters are reset. - assertRefCount(t, a, types.BlockRoots, 1) - assertRefCount(t, a, types.StateRoots, 1) - assertRefCount(t, b, types.BlockRoots, 1) - assertRefCount(t, b, types.StateRoots, 1) -} - -func TestStateReferenceCopy_NoUnexpectedRandaoMutation_Phase0(t *testing.T) { - val1, val2 := bytesutil.ToBytes32([]byte("foo")), bytesutil.ToBytes32([]byte("bar")) - s, err := InitializeFromProtoUnsafePhase0(ðpb.BeaconState{ - RandaoMixes: [][]byte{ - val1[:], - }, - }) - require.NoError(t, err) - a, ok := s.(*BeaconState) - require.Equal(t, true, ok) - require.NoError(t, err) - assertRefCount(t, a, types.RandaoMixes, 1) - - // Copy, increases reference count. - copied := a.Copy() - b, ok := copied.(*BeaconState) - require.Equal(t, true, ok) - assertRefCount(t, a, types.RandaoMixes, 2) - assertRefCount(t, b, types.RandaoMixes, 2) - - // Assert shared state. - mixesA := a.RandaoMixes() - mixesB := b.RandaoMixes() - assertValFound(t, mixesA, val1[:]) - assertValFound(t, mixesB, val1[:]) - - // Mutator should only affect calling state: a. - require.NoError(t, a.UpdateRandaoMixesAtIndex(0, val2)) - - // Assert no shared state mutation occurred only on state a (copy on write). - assertValFound(t, a.RandaoMixes(), val2[:]) - assertValNotFound(t, a.RandaoMixes(), val1[:]) - assertValFound(t, b.RandaoMixes(), val1[:]) - assertValNotFound(t, b.RandaoMixes(), val2[:]) - assertValFound(t, mixesB, val1[:]) - assertValNotFound(t, mixesB, val2[:]) - assert.DeepEqual(t, val2[:], a.RandaoMixes()[0], "Expected mutation not found") - assert.DeepEqual(t, val1[:], mixesB[0], "Unexpected mutation found") - - // Copy on write happened, reference counters are reset. - assertRefCount(t, a, types.RandaoMixes, 1) - assertRefCount(t, b, types.RandaoMixes, 1) -} - -func TestStateReferenceCopy_NoUnexpectedRandaoMutation_Altair(t *testing.T) { - val1, val2 := bytesutil.ToBytes32([]byte("foo")), bytesutil.ToBytes32([]byte("bar")) - s, err := InitializeFromProtoUnsafeAltair(ðpb.BeaconStateAltair{ - RandaoMixes: [][]byte{ - val1[:], - }, - }) - require.NoError(t, err) - a, ok := s.(*BeaconState) - require.Equal(t, true, ok) - require.NoError(t, err) - assertRefCount(t, a, types.RandaoMixes, 1) - - // Copy, increases reference count. - copied := a.Copy() - b, ok := copied.(*BeaconState) - require.Equal(t, true, ok) - assertRefCount(t, a, types.RandaoMixes, 2) - assertRefCount(t, b, types.RandaoMixes, 2) - - // Assert shared state. - mixesA := a.RandaoMixes() - mixesB := b.RandaoMixes() - assertValFound(t, mixesA, val1[:]) - assertValFound(t, mixesB, val1[:]) - - // Mutator should only affect calling state: a. - require.NoError(t, a.UpdateRandaoMixesAtIndex(0, val2)) - - // Assert no shared state mutation occurred only on state a (copy on write). - assertValFound(t, a.RandaoMixes(), val2[:]) - assertValNotFound(t, a.RandaoMixes(), val1[:]) - assertValFound(t, b.RandaoMixes(), val1[:]) - assertValNotFound(t, b.RandaoMixes(), val2[:]) - assertValFound(t, mixesB, val1[:]) - assertValNotFound(t, mixesB, val2[:]) - assert.DeepEqual(t, val2[:], a.RandaoMixes()[0], "Expected mutation not found") - assert.DeepEqual(t, val1[:], mixesB[0], "Unexpected mutation found") - - // Copy on write happened, reference counters are reset. - assertRefCount(t, a, types.RandaoMixes, 1) - assertRefCount(t, b, types.RandaoMixes, 1) -} - -func TestStateReferenceCopy_NoUnexpectedRandaoMutation_Bellatrix(t *testing.T) { - val1, val2 := bytesutil.ToBytes32([]byte("foo")), bytesutil.ToBytes32([]byte("bar")) - s, err := InitializeFromProtoUnsafeBellatrix(ðpb.BeaconStateBellatrix{ - RandaoMixes: [][]byte{ - val1[:], - }, - }) - require.NoError(t, err) - a, ok := s.(*BeaconState) - require.Equal(t, true, ok) - require.NoError(t, err) - assertRefCount(t, a, types.RandaoMixes, 1) - - // Copy, increases reference count. - copied := a.Copy() - b, ok := copied.(*BeaconState) - require.Equal(t, true, ok) - assertRefCount(t, a, types.RandaoMixes, 2) - assertRefCount(t, b, types.RandaoMixes, 2) - - // Assert shared state. - mixesA := a.RandaoMixes() - mixesB := b.RandaoMixes() - assertValFound(t, mixesA, val1[:]) - assertValFound(t, mixesB, val1[:]) - - // Mutator should only affect calling state: a. - require.NoError(t, a.UpdateRandaoMixesAtIndex(0, val2)) - - // Assert no shared state mutation occurred only on state a (copy on write). - assertValFound(t, a.RandaoMixes(), val2[:]) - assertValNotFound(t, a.RandaoMixes(), val1[:]) - assertValFound(t, b.RandaoMixes(), val1[:]) - assertValNotFound(t, b.RandaoMixes(), val2[:]) - assertValFound(t, mixesB, val1[:]) - assertValNotFound(t, mixesB, val2[:]) - assert.DeepEqual(t, val2[:], a.RandaoMixes()[0], "Expected mutation not found") - assert.DeepEqual(t, val1[:], mixesB[0], "Unexpected mutation found") - - // Copy on write happened, reference counters are reset. - assertRefCount(t, a, types.RandaoMixes, 1) - assertRefCount(t, b, types.RandaoMixes, 1) -} - -func TestStateReferenceCopy_NoUnexpectedRandaoMutation_Capella(t *testing.T) { - val1, val2 := bytesutil.ToBytes32([]byte("foo")), bytesutil.ToBytes32([]byte("bar")) - s, err := InitializeFromProtoUnsafeCapella(ðpb.BeaconStateCapella{ - RandaoMixes: [][]byte{ - val1[:], - }, - }) - require.NoError(t, err) - a, ok := s.(*BeaconState) - require.Equal(t, true, ok) - require.NoError(t, err) - assertRefCount(t, a, types.RandaoMixes, 1) - - // Copy, increases reference count. - copied := a.Copy() - b, ok := copied.(*BeaconState) - require.Equal(t, true, ok) - assertRefCount(t, a, types.RandaoMixes, 2) - assertRefCount(t, b, types.RandaoMixes, 2) - - // Assert shared state. - mixesA := a.RandaoMixes() - mixesB := b.RandaoMixes() - assertValFound(t, mixesA, val1[:]) - assertValFound(t, mixesB, val1[:]) - - // Mutator should only affect calling state: a. - require.NoError(t, a.UpdateRandaoMixesAtIndex(0, val2)) - - // Assert no shared state mutation occurred only on state a (copy on write). - assertValFound(t, a.RandaoMixes(), val2[:]) - assertValNotFound(t, a.RandaoMixes(), val1[:]) - assertValFound(t, b.RandaoMixes(), val1[:]) - assertValNotFound(t, b.RandaoMixes(), val2[:]) - assertValFound(t, mixesB, val1[:]) - assertValNotFound(t, mixesB, val2[:]) - assert.DeepEqual(t, val2[:], a.RandaoMixes()[0], "Expected mutation not found") - assert.DeepEqual(t, val1[:], mixesB[0], "Unexpected mutation found") - - // Copy on write happened, reference counters are reset. - assertRefCount(t, a, types.RandaoMixes, 1) - assertRefCount(t, b, types.RandaoMixes, 1) -} - -func TestStateReferenceCopy_NoUnexpectedRandaoMutation_Deneb(t *testing.T) { - val1, val2 := bytesutil.ToBytes32([]byte("foo")), bytesutil.ToBytes32([]byte("bar")) - s, err := InitializeFromProtoUnsafeDeneb(ðpb.BeaconStateDeneb{ - RandaoMixes: [][]byte{ - val1[:], - }, - }) - require.NoError(t, err) - a, ok := s.(*BeaconState) - require.Equal(t, true, ok) - require.NoError(t, err) - assertRefCount(t, a, types.RandaoMixes, 1) - - // Copy, increases reference count. - copied := a.Copy() - b, ok := copied.(*BeaconState) - require.Equal(t, true, ok) - assertRefCount(t, a, types.RandaoMixes, 2) - assertRefCount(t, b, types.RandaoMixes, 2) - - // Assert shared state. - mixesA := a.RandaoMixes() - mixesB := b.RandaoMixes() - assertValFound(t, mixesA, val1[:]) - assertValFound(t, mixesB, val1[:]) - - // Mutator should only affect calling state: a. - require.NoError(t, a.UpdateRandaoMixesAtIndex(0, val2)) - - // Assert no shared state mutation occurred only on state a (copy on write). - assertValFound(t, a.RandaoMixes(), val2[:]) - assertValNotFound(t, a.RandaoMixes(), val1[:]) - assertValFound(t, b.RandaoMixes(), val1[:]) - assertValNotFound(t, b.RandaoMixes(), val2[:]) - assertValFound(t, mixesB, val1[:]) - assertValNotFound(t, mixesB, val2[:]) - assert.DeepEqual(t, val2[:], a.RandaoMixes()[0], "Expected mutation not found") - assert.DeepEqual(t, val1[:], mixesB[0], "Unexpected mutation found") - - // Copy on write happened, reference counters are reset. - assertRefCount(t, a, types.RandaoMixes, 1) - assertRefCount(t, b, types.RandaoMixes, 1) + assertRefCount(t, a, types.Slashings, 1) + assertRefCount(t, b, types.Slashings, 1) } func TestStateReferenceCopy_NoUnexpectedAttestationsMutation(t *testing.T) { @@ -1017,10 +711,6 @@ func TestValidatorReferences_RemainsConsistent_Bellatrix(t *testing.T) { } func TestValidatorReferences_ApplyValidator_BalancesRead(t *testing.T) { - resetCfg := features.InitWithReset(&features.Flags{ - EnableExperimentalState: true, - }) - defer resetCfg() s, err := InitializeFromProtoUnsafeAltair(ðpb.BeaconStateAltair{ Validators: []*ethpb.Validator{ {PublicKey: []byte{'A'}}, @@ -1061,7 +751,7 @@ func assertRefCount(t *testing.T, b *BeaconState, idx types.FieldIndex, want uin } // assertValFound checks whether item with a given value exists in list. -func assertValFound(t *testing.T, vals [][]byte, val []byte) { +func assertValFound(t *testing.T, vals []uint64, val uint64) { for i := range vals { if reflect.DeepEqual(vals[i], val) { return @@ -1072,7 +762,7 @@ func assertValFound(t *testing.T, vals [][]byte, val []byte) { } // assertValNotFound checks whether item with a given value doesn't exist in list. -func assertValNotFound(t *testing.T, vals [][]byte, val []byte) { +func assertValNotFound(t *testing.T, vals []uint64, val uint64) { for i := range vals { if reflect.DeepEqual(vals[i], val) { t.Log(string(debug.Stack())) diff --git a/beacon-chain/state/state-native/setters_block.go b/beacon-chain/state/state-native/setters_block.go index a39f181c95..36569fc0c4 100644 --- a/beacon-chain/state/state-native/setters_block.go +++ b/beacon-chain/state/state-native/setters_block.go @@ -2,10 +2,6 @@ package state_native import ( "github.com/OffchainLabs/prysm/v6/beacon-chain/state/state-native/types" - "github.com/OffchainLabs/prysm/v6/beacon-chain/state/stateutil" - "github.com/OffchainLabs/prysm/v6/config/features" - fieldparams "github.com/OffchainLabs/prysm/v6/config/fieldparams" - consensus_types "github.com/OffchainLabs/prysm/v6/consensus-types" ethpb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1" "github.com/pkg/errors" ) @@ -26,21 +22,10 @@ func (b *BeaconState) SetBlockRoots(val [][]byte) error { b.lock.Lock() defer b.lock.Unlock() - if features.Get().EnableExperimentalState { - if b.blockRootsMultiValue != nil { - b.blockRootsMultiValue.Detach(b) - } - b.blockRootsMultiValue = NewMultiValueBlockRoots(val) - } else { - b.sharedFieldReferences[types.BlockRoots].MinusRef() - b.sharedFieldReferences[types.BlockRoots] = stateutil.NewRef(1) - - rootsArr := make([][32]byte, fieldparams.BlockRootsLength) - for i := 0; i < len(rootsArr); i++ { - copy(rootsArr[i][:], val[i]) - } - b.blockRoots = rootsArr + if b.blockRootsMultiValue != nil { + b.blockRootsMultiValue.Detach(b) } + b.blockRootsMultiValue = NewMultiValueBlockRoots(val) b.markFieldAsDirty(types.BlockRoots) b.rebuildTrie[types.BlockRoots] = true @@ -53,25 +38,8 @@ func (b *BeaconState) UpdateBlockRootAtIndex(idx uint64, blockRoot [32]byte) err b.lock.Lock() defer b.lock.Unlock() - if features.Get().EnableExperimentalState { - if err := b.blockRootsMultiValue.UpdateAt(b, idx, blockRoot); err != nil { - return errors.Wrap(err, "could not update block roots") - } - } else { - if uint64(len(b.blockRoots)) <= idx { - return errors.Wrapf(consensus_types.ErrOutOfBounds, "block root index %d does not exist", idx) - } - - r := b.blockRoots - if ref := b.sharedFieldReferences[types.BlockRoots]; ref.Refs() > 1 { - // Copy elements in underlying array by reference. - r = make([][32]byte, len(b.blockRoots)) - copy(r, b.blockRoots) - ref.MinusRef() - b.sharedFieldReferences[types.BlockRoots] = stateutil.NewRef(1) - } - r[idx] = blockRoot - b.blockRoots = r + if err := b.blockRootsMultiValue.UpdateAt(b, idx, blockRoot); err != nil { + return errors.Wrap(err, "could not update block roots") } b.markFieldAsDirty(types.BlockRoots) diff --git a/beacon-chain/state/state-native/setters_randao.go b/beacon-chain/state/state-native/setters_randao.go index c8570a315e..12b4d188ce 100644 --- a/beacon-chain/state/state-native/setters_randao.go +++ b/beacon-chain/state/state-native/setters_randao.go @@ -2,10 +2,6 @@ package state_native import ( "github.com/OffchainLabs/prysm/v6/beacon-chain/state/state-native/types" - "github.com/OffchainLabs/prysm/v6/beacon-chain/state/stateutil" - "github.com/OffchainLabs/prysm/v6/config/features" - fieldparams "github.com/OffchainLabs/prysm/v6/config/fieldparams" - consensus_types "github.com/OffchainLabs/prysm/v6/consensus-types" "github.com/pkg/errors" ) @@ -15,21 +11,10 @@ func (b *BeaconState) SetRandaoMixes(val [][]byte) error { b.lock.Lock() defer b.lock.Unlock() - if features.Get().EnableExperimentalState { - if b.randaoMixesMultiValue != nil { - b.randaoMixesMultiValue.Detach(b) - } - b.randaoMixesMultiValue = NewMultiValueRandaoMixes(val) - } else { - b.sharedFieldReferences[types.RandaoMixes].MinusRef() - b.sharedFieldReferences[types.RandaoMixes] = stateutil.NewRef(1) - - rootsArr := make([][32]byte, fieldparams.RandaoMixesLength) - for i := 0; i < len(rootsArr); i++ { - copy(rootsArr[i][:], val[i]) - } - b.randaoMixes = rootsArr + if b.randaoMixesMultiValue != nil { + b.randaoMixesMultiValue.Detach(b) } + b.randaoMixesMultiValue = NewMultiValueRandaoMixes(val) b.markFieldAsDirty(types.RandaoMixes) b.rebuildTrie[types.RandaoMixes] = true @@ -39,29 +24,8 @@ func (b *BeaconState) SetRandaoMixes(val [][]byte) error { // UpdateRandaoMixesAtIndex for the beacon state. Updates the randao mixes // at a specific index to a new value. func (b *BeaconState) UpdateRandaoMixesAtIndex(idx uint64, val [32]byte) error { - if features.Get().EnableExperimentalState { - if err := b.randaoMixesMultiValue.UpdateAt(b, idx, val); err != nil { - return errors.Wrap(err, "could not update randao mixes") - } - } else { - if uint64(len(b.randaoMixes)) <= idx { - return errors.Wrapf(consensus_types.ErrOutOfBounds, "randao mix index %d does not exist", idx) - } - - b.lock.Lock() - - m := b.randaoMixes - if ref := b.sharedFieldReferences[types.RandaoMixes]; ref.Refs() > 1 { - // Copy elements in underlying array by reference. - m = make([][32]byte, len(b.randaoMixes)) - copy(m, b.randaoMixes) - ref.MinusRef() - b.sharedFieldReferences[types.RandaoMixes] = stateutil.NewRef(1) - } - m[idx] = val - b.randaoMixes = m - - b.lock.Unlock() + if err := b.randaoMixesMultiValue.UpdateAt(b, idx, val); err != nil { + return errors.Wrap(err, "could not update randao mixes") } b.lock.Lock() diff --git a/beacon-chain/state/state-native/setters_state.go b/beacon-chain/state/state-native/setters_state.go index 8126c6e3fe..28d69417c4 100644 --- a/beacon-chain/state/state-native/setters_state.go +++ b/beacon-chain/state/state-native/setters_state.go @@ -2,10 +2,6 @@ package state_native import ( "github.com/OffchainLabs/prysm/v6/beacon-chain/state/state-native/types" - "github.com/OffchainLabs/prysm/v6/beacon-chain/state/stateutil" - "github.com/OffchainLabs/prysm/v6/config/features" - fieldparams "github.com/OffchainLabs/prysm/v6/config/fieldparams" - consensus_types "github.com/OffchainLabs/prysm/v6/consensus-types" "github.com/pkg/errors" ) @@ -15,21 +11,10 @@ func (b *BeaconState) SetStateRoots(val [][]byte) error { b.lock.Lock() defer b.lock.Unlock() - if features.Get().EnableExperimentalState { - if b.stateRootsMultiValue != nil { - b.stateRootsMultiValue.Detach(b) - } - b.stateRootsMultiValue = NewMultiValueStateRoots(val) - } else { - b.sharedFieldReferences[types.StateRoots].MinusRef() - b.sharedFieldReferences[types.StateRoots] = stateutil.NewRef(1) - - rootsArr := make([][32]byte, fieldparams.StateRootsLength) - for i := 0; i < len(rootsArr); i++ { - copy(rootsArr[i][:], val[i]) - } - b.stateRoots = rootsArr + if b.stateRootsMultiValue != nil { + b.stateRootsMultiValue.Detach(b) } + b.stateRootsMultiValue = NewMultiValueStateRoots(val) b.markFieldAsDirty(types.StateRoots) b.rebuildTrie[types.StateRoots] = true @@ -39,29 +24,8 @@ func (b *BeaconState) SetStateRoots(val [][]byte) error { // UpdateStateRootAtIndex for the beacon state. Updates the state root // at a specific index to a new value. func (b *BeaconState) UpdateStateRootAtIndex(idx uint64, stateRoot [32]byte) error { - if features.Get().EnableExperimentalState { - if err := b.stateRootsMultiValue.UpdateAt(b, idx, stateRoot); err != nil { - return errors.Wrap(err, "could not update state roots") - } - } else { - if uint64(len(b.stateRoots)) <= idx { - return errors.Wrapf(consensus_types.ErrOutOfBounds, "state root index %d does not exist", idx) - } - - b.lock.Lock() - - r := b.stateRoots - if ref := b.sharedFieldReferences[types.StateRoots]; ref.Refs() > 1 { - // Copy elements in underlying array by reference. - r = make([][32]byte, len(b.stateRoots)) - copy(r, b.stateRoots) - ref.MinusRef() - b.sharedFieldReferences[types.StateRoots] = stateutil.NewRef(1) - } - r[idx] = stateRoot - b.stateRoots = r - - b.lock.Unlock() + if err := b.stateRootsMultiValue.UpdateAt(b, idx, stateRoot); err != nil { + return errors.Wrap(err, "could not update state roots") } b.lock.Lock() diff --git a/beacon-chain/state/state-native/setters_validator.go b/beacon-chain/state/state-native/setters_validator.go index 34c7d69d76..3e98b4bcce 100644 --- a/beacon-chain/state/state-native/setters_validator.go +++ b/beacon-chain/state/state-native/setters_validator.go @@ -4,9 +4,6 @@ import ( "github.com/OffchainLabs/prysm/v6/beacon-chain/state" "github.com/OffchainLabs/prysm/v6/beacon-chain/state/state-native/types" "github.com/OffchainLabs/prysm/v6/beacon-chain/state/stateutil" - "github.com/OffchainLabs/prysm/v6/config/features" - "github.com/OffchainLabs/prysm/v6/config/params" - consensus_types "github.com/OffchainLabs/prysm/v6/consensus-types" "github.com/OffchainLabs/prysm/v6/consensus-types/primitives" "github.com/OffchainLabs/prysm/v6/encoding/bytesutil" ethpb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1" @@ -20,16 +17,10 @@ func (b *BeaconState) SetValidators(val []*ethpb.Validator) error { b.lock.Lock() defer b.lock.Unlock() - if features.Get().EnableExperimentalState { - if b.validatorsMultiValue != nil { - b.validatorsMultiValue.Detach(b) - } - b.validatorsMultiValue = NewMultiValueValidators(val) - } else { - b.validators = val - b.sharedFieldReferences[types.Validators].MinusRef() - b.sharedFieldReferences[types.Validators] = stateutil.NewRef(1) + if b.validatorsMultiValue != nil { + b.validatorsMultiValue.Detach(b) } + b.validatorsMultiValue = NewMultiValueValidators(val) b.markFieldAsDirty(types.Validators) b.rebuildTrie[types.Validators] = true @@ -41,58 +32,26 @@ func (b *BeaconState) SetValidators(val []*ethpb.Validator) error { // validator registry. func (b *BeaconState) ApplyToEveryValidator(f func(idx int, val state.ReadOnlyValidator) (*ethpb.Validator, error)) error { var changedVals []uint64 - if features.Get().EnableExperimentalState { - l := b.validatorsMultiValue.Len(b) - for i := 0; i < l; i++ { - v, err := b.validatorsMultiValue.At(b, uint64(i)) - if err != nil { - return err - } - ro, err := NewValidator(v) - if err != nil { - return err - } - newVal, err := f(i, ro) - if err != nil { - return err - } - if newVal != nil { - changedVals = append(changedVals, uint64(i)) - if err = b.validatorsMultiValue.UpdateAt(b, uint64(i), newVal); err != nil { - return errors.Wrapf(err, "could not update validator at index %d", i) - } + l := b.validatorsMultiValue.Len(b) + for i := 0; i < l; i++ { + v, err := b.validatorsMultiValue.At(b, uint64(i)) + if err != nil { + return err + } + ro, err := NewValidator(v) + if err != nil { + return err + } + newVal, err := f(i, ro) + if err != nil { + return err + } + if newVal != nil { + changedVals = append(changedVals, uint64(i)) + if err = b.validatorsMultiValue.UpdateAt(b, uint64(i), newVal); err != nil { + return errors.Wrapf(err, "could not update validator at index %d", i) } } - } else { - b.lock.Lock() - - v := b.validators - if ref := b.sharedFieldReferences[types.Validators]; ref.Refs() > 1 { - v = b.validatorsReferences() - ref.MinusRef() - b.sharedFieldReferences[types.Validators] = stateutil.NewRef(1) - } - - b.lock.Unlock() - - for i, val := range v { - ro, err := NewValidator(val) - if err != nil { - return err - } - newVal, err := f(i, ro) - if err != nil { - return err - } - if newVal != nil { - changedVals = append(changedVals, uint64(i)) - v[i] = newVal - } - } - - b.lock.Lock() - b.validators = v - b.lock.Unlock() } b.lock.Lock() @@ -108,27 +67,8 @@ func (b *BeaconState) ApplyToEveryValidator(f func(idx int, val state.ReadOnlyVa // UpdateValidatorAtIndex for the beacon state. Updates the validator // at a specific index to a new value. func (b *BeaconState) UpdateValidatorAtIndex(idx primitives.ValidatorIndex, val *ethpb.Validator) error { - if features.Get().EnableExperimentalState { - if err := b.validatorsMultiValue.UpdateAt(b, uint64(idx), val); err != nil { - return errors.Wrap(err, "could not update validator") - } - } else { - if uint64(len(b.validators)) <= uint64(idx) { - return errors.Wrapf(consensus_types.ErrOutOfBounds, "validator index %d does not exist", idx) - } - - b.lock.Lock() - - v := b.validators - if ref := b.sharedFieldReferences[types.Validators]; ref.Refs() > 1 { - v = b.validatorsReferences() - ref.MinusRef() - b.sharedFieldReferences[types.Validators] = stateutil.NewRef(1) - } - v[idx] = val - b.validators = v - - b.lock.Unlock() + if err := b.validatorsMultiValue.UpdateAt(b, uint64(idx), val); err != nil { + return errors.Wrap(err, "could not update validator") } b.lock.Lock() @@ -145,16 +85,10 @@ func (b *BeaconState) SetBalances(val []uint64) error { b.lock.Lock() defer b.lock.Unlock() - if features.Get().EnableExperimentalState { - if b.balancesMultiValue != nil { - b.balancesMultiValue.Detach(b) - } - b.balancesMultiValue = NewMultiValueBalances(val) - } else { - b.sharedFieldReferences[types.Balances].MinusRef() - b.sharedFieldReferences[types.Balances] = stateutil.NewRef(1) - b.balances = val + if b.balancesMultiValue != nil { + b.balancesMultiValue.Detach(b) } + b.balancesMultiValue = NewMultiValueBalances(val) b.markFieldAsDirty(types.Balances) b.rebuildTrie[types.Balances] = true @@ -164,27 +98,8 @@ func (b *BeaconState) SetBalances(val []uint64) error { // UpdateBalancesAtIndex for the beacon state. This method updates the balance // at a specific index to a new value. func (b *BeaconState) UpdateBalancesAtIndex(idx primitives.ValidatorIndex, val uint64) error { - if features.Get().EnableExperimentalState { - if err := b.balancesMultiValue.UpdateAt(b, uint64(idx), val); err != nil { - return errors.Wrap(err, "could not update balances") - } - } else { - if uint64(len(b.balances)) <= uint64(idx) { - return errors.Wrapf(consensus_types.ErrOutOfBounds, "balance index %d does not exist", idx) - } - - b.lock.Lock() - - bals := b.balances - if b.sharedFieldReferences[types.Balances].Refs() > 1 { - bals = b.balancesVal() - b.sharedFieldReferences[types.Balances].MinusRef() - b.sharedFieldReferences[types.Balances] = stateutil.NewRef(1) - } - bals[idx] = val - b.balances = bals - - b.lock.Unlock() + if err := b.balancesMultiValue.UpdateAt(b, uint64(idx), val); err != nil { + return errors.Wrap(err, "could not update balances") } b.lock.Lock() @@ -236,25 +151,8 @@ func (b *BeaconState) UpdateSlashingsAtIndex(idx, val uint64) error { // AppendValidator for the beacon state. Appends the new value // to the end of list. func (b *BeaconState) AppendValidator(val *ethpb.Validator) error { - var valIdx primitives.ValidatorIndex - if features.Get().EnableExperimentalState { - b.validatorsMultiValue.Append(b, val) - valIdx = primitives.ValidatorIndex(b.validatorsMultiValue.Len(b) - 1) - } else { - b.lock.Lock() - - vals := b.validators - if b.sharedFieldReferences[types.Validators].Refs() > 1 { - vals = b.validatorsReferences() - b.sharedFieldReferences[types.Validators].MinusRef() - b.sharedFieldReferences[types.Validators] = stateutil.NewRef(1) - } - - b.validators = append(vals, val) - valIdx = primitives.ValidatorIndex(len(b.validators) - 1) - - b.lock.Unlock() - } + b.validatorsMultiValue.Append(b, val) + valIdx := primitives.ValidatorIndex(b.validatorsMultiValue.Len(b) - 1) b.lock.Lock() defer b.lock.Unlock() @@ -268,26 +166,8 @@ func (b *BeaconState) AppendValidator(val *ethpb.Validator) error { // AppendBalance for the beacon state. Appends the new value // to the end of list. func (b *BeaconState) AppendBalance(bal uint64) error { - var balIdx uint64 - if features.Get().EnableExperimentalState { - b.balancesMultiValue.Append(b, bal) - balIdx = uint64(b.balancesMultiValue.Len(b) - 1) - } else { - b.lock.Lock() - - bals := b.balances - if b.sharedFieldReferences[types.Balances].Refs() > 1 { - bals = make([]uint64, 0, len(b.balances)+int(params.BeaconConfig().MaxDeposits)) - bals = append(bals, b.balances...) - b.sharedFieldReferences[types.Balances].MinusRef() - b.sharedFieldReferences[types.Balances] = stateutil.NewRef(1) - } - - b.balances = append(bals, bal) - balIdx = uint64(len(b.balances) - 1) - - b.lock.Unlock() - } + b.balancesMultiValue.Append(b, bal) + balIdx := uint64(b.balancesMultiValue.Len(b) - 1) b.lock.Lock() defer b.lock.Unlock() @@ -303,22 +183,7 @@ func (b *BeaconState) AppendInactivityScore(s uint64) error { return errNotSupported("AppendInactivityScore", b.version) } - if features.Get().EnableExperimentalState { - b.inactivityScoresMultiValue.Append(b, s) - } else { - b.lock.Lock() - - scores := b.inactivityScores - if b.sharedFieldReferences[types.InactivityScores].Refs() > 1 { - scores = make([]uint64, 0, len(b.inactivityScores)+int(params.BeaconConfig().MaxDeposits)) - scores = append(scores, b.inactivityScores...) - b.sharedFieldReferences[types.InactivityScores].MinusRef() - b.sharedFieldReferences[types.InactivityScores] = stateutil.NewRef(1) - } - b.inactivityScores = append(scores, s) - - b.lock.Unlock() - } + b.inactivityScoresMultiValue.Append(b, s) b.lock.Lock() defer b.lock.Unlock() @@ -337,16 +202,10 @@ func (b *BeaconState) SetInactivityScores(val []uint64) error { return errNotSupported("SetInactivityScores", b.version) } - if features.Get().EnableExperimentalState { - if b.inactivityScoresMultiValue != nil { - b.inactivityScoresMultiValue.Detach(b) - } - b.inactivityScoresMultiValue = NewMultiValueInactivityScores(val) - } else { - b.sharedFieldReferences[types.InactivityScores].MinusRef() - b.sharedFieldReferences[types.InactivityScores] = stateutil.NewRef(1) - b.inactivityScores = val + if b.inactivityScoresMultiValue != nil { + b.inactivityScoresMultiValue.Detach(b) } + b.inactivityScoresMultiValue = NewMultiValueInactivityScores(val) b.markFieldAsDirty(types.InactivityScores) return nil diff --git a/beacon-chain/state/state-native/state_trie.go b/beacon-chain/state/state-native/state_trie.go index 18ef86595e..977f947a76 100644 --- a/beacon-chain/state/state-native/state_trie.go +++ b/beacon-chain/state/state-native/state_trie.go @@ -11,7 +11,6 @@ import ( customtypes "github.com/OffchainLabs/prysm/v6/beacon-chain/state/state-native/custom-types" "github.com/OffchainLabs/prysm/v6/beacon-chain/state/state-native/types" "github.com/OffchainLabs/prysm/v6/beacon-chain/state/stateutil" - "github.com/OffchainLabs/prysm/v6/config/features" fieldparams "github.com/OffchainLabs/prysm/v6/config/fieldparams" "github.com/OffchainLabs/prysm/v6/config/params" "github.com/OffchainLabs/prysm/v6/consensus-types/primitives" @@ -116,20 +115,13 @@ var ( ) const ( - phase0SharedFieldRefCount = 10 - altairSharedFieldRefCount = 11 - bellatrixSharedFieldRefCount = 12 - capellaSharedFieldRefCount = 13 - denebSharedFieldRefCount = 13 - electraSharedFieldRefCount = 16 - fuluSharedFieldRefCount = 17 - experimentalStatePhase0SharedFieldRefCount = 5 - experimentalStateAltairSharedFieldRefCount = 5 - experimentalStateBellatrixSharedFieldRefCount = 6 - experimentalStateCapellaSharedFieldRefCount = 7 - experimentalStateDenebSharedFieldRefCount = 7 - experimentalStateElectraSharedFieldRefCount = 10 - experimentalStateFuluSharedFieldRefCount = 11 + phase0SharedFieldRefCount = 5 + altairSharedFieldRefCount = 5 + bellatrixSharedFieldRefCount = 6 + capellaSharedFieldRefCount = 7 + denebSharedFieldRefCount = 7 + electraSharedFieldRefCount = 10 + fuluSharedFieldRefCount = 11 ) // InitializeFromProtoPhase0 the beacon state from a protobuf representation. @@ -208,37 +200,12 @@ func InitializeFromProtoUnsafePhase0(st *ethpb.BeaconState) (state.BeaconState, valMapHandler: stateutil.NewValMapHandler(st.Validators), } - if features.Get().EnableExperimentalState { - b.blockRootsMultiValue = NewMultiValueBlockRoots(st.BlockRoots) - b.stateRootsMultiValue = NewMultiValueStateRoots(st.StateRoots) - b.randaoMixesMultiValue = NewMultiValueRandaoMixes(st.RandaoMixes) - b.balancesMultiValue = NewMultiValueBalances(st.Balances) - b.validatorsMultiValue = NewMultiValueValidators(st.Validators) - b.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, experimentalStatePhase0SharedFieldRefCount) - } else { - bRoots := make([][32]byte, fieldparams.BlockRootsLength) - for i, r := range st.BlockRoots { - bRoots[i] = bytesutil.ToBytes32(r) - } - b.blockRoots = bRoots - - sRoots := make([][32]byte, fieldparams.StateRootsLength) - for i, r := range st.StateRoots { - sRoots[i] = bytesutil.ToBytes32(r) - } - b.stateRoots = sRoots - - mixes := make([][32]byte, fieldparams.RandaoMixesLength) - for i, m := range st.RandaoMixes { - mixes[i] = bytesutil.ToBytes32(m) - } - b.randaoMixes = mixes - - b.balances = st.Balances - b.validators = st.Validators - - b.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, phase0SharedFieldRefCount) - } + b.blockRootsMultiValue = NewMultiValueBlockRoots(st.BlockRoots) + b.stateRootsMultiValue = NewMultiValueStateRoots(st.StateRoots) + b.randaoMixesMultiValue = NewMultiValueRandaoMixes(st.RandaoMixes) + b.balancesMultiValue = NewMultiValueBalances(st.Balances) + b.validatorsMultiValue = NewMultiValueValidators(st.Validators) + b.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, phase0SharedFieldRefCount) for _, f := range phase0Fields { b.dirtyFields[f] = true @@ -257,13 +224,6 @@ func InitializeFromProtoUnsafePhase0(st *ethpb.BeaconState) (state.BeaconState, b.sharedFieldReferences[types.Slashings] = stateutil.NewRef(1) b.sharedFieldReferences[types.PreviousEpochAttestations] = stateutil.NewRef(1) b.sharedFieldReferences[types.CurrentEpochAttestations] = stateutil.NewRef(1) - if !features.Get().EnableExperimentalState { - b.sharedFieldReferences[types.BlockRoots] = stateutil.NewRef(1) - b.sharedFieldReferences[types.StateRoots] = stateutil.NewRef(1) - b.sharedFieldReferences[types.RandaoMixes] = stateutil.NewRef(1) - b.sharedFieldReferences[types.Balances] = stateutil.NewRef(1) - b.sharedFieldReferences[types.Validators] = stateutil.NewRef(1) - } state.Count.Inc() // Finalizer runs when dst is being destroyed in garbage collection. @@ -314,39 +274,13 @@ func InitializeFromProtoUnsafeAltair(st *ethpb.BeaconStateAltair) (state.BeaconS valMapHandler: stateutil.NewValMapHandler(st.Validators), } - if features.Get().EnableExperimentalState { - b.blockRootsMultiValue = NewMultiValueBlockRoots(st.BlockRoots) - b.stateRootsMultiValue = NewMultiValueStateRoots(st.StateRoots) - b.randaoMixesMultiValue = NewMultiValueRandaoMixes(st.RandaoMixes) - b.balancesMultiValue = NewMultiValueBalances(st.Balances) - b.validatorsMultiValue = NewMultiValueValidators(st.Validators) - b.inactivityScoresMultiValue = NewMultiValueInactivityScores(st.InactivityScores) - b.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, experimentalStateAltairSharedFieldRefCount) - } else { - bRoots := make([][32]byte, fieldparams.BlockRootsLength) - for i, r := range st.BlockRoots { - bRoots[i] = bytesutil.ToBytes32(r) - } - b.blockRoots = bRoots - - sRoots := make([][32]byte, fieldparams.StateRootsLength) - for i, r := range st.StateRoots { - sRoots[i] = bytesutil.ToBytes32(r) - } - b.stateRoots = sRoots - - mixes := make([][32]byte, fieldparams.RandaoMixesLength) - for i, m := range st.RandaoMixes { - mixes[i] = bytesutil.ToBytes32(m) - } - b.randaoMixes = mixes - - b.balances = st.Balances - b.validators = st.Validators - b.inactivityScores = st.InactivityScores - - b.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, altairSharedFieldRefCount) - } + b.blockRootsMultiValue = NewMultiValueBlockRoots(st.BlockRoots) + b.stateRootsMultiValue = NewMultiValueStateRoots(st.StateRoots) + b.randaoMixesMultiValue = NewMultiValueRandaoMixes(st.RandaoMixes) + b.balancesMultiValue = NewMultiValueBalances(st.Balances) + b.validatorsMultiValue = NewMultiValueValidators(st.Validators) + b.inactivityScoresMultiValue = NewMultiValueInactivityScores(st.InactivityScores) + b.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, altairSharedFieldRefCount) for _, f := range altairFields { b.dirtyFields[f] = true @@ -365,14 +299,6 @@ func InitializeFromProtoUnsafeAltair(st *ethpb.BeaconStateAltair) (state.BeaconS b.sharedFieldReferences[types.Slashings] = stateutil.NewRef(1) b.sharedFieldReferences[types.PreviousEpochParticipationBits] = stateutil.NewRef(1) // New in Altair. b.sharedFieldReferences[types.CurrentEpochParticipationBits] = stateutil.NewRef(1) // New in Altair. - if !features.Get().EnableExperimentalState { - b.sharedFieldReferences[types.BlockRoots] = stateutil.NewRef(1) - b.sharedFieldReferences[types.StateRoots] = stateutil.NewRef(1) - b.sharedFieldReferences[types.RandaoMixes] = stateutil.NewRef(1) - b.sharedFieldReferences[types.Balances] = stateutil.NewRef(1) - b.sharedFieldReferences[types.Validators] = stateutil.NewRef(1) - b.sharedFieldReferences[types.InactivityScores] = stateutil.NewRef(1) - } state.Count.Inc() // Finalizer runs when dst is being destroyed in garbage collection. @@ -424,39 +350,13 @@ func InitializeFromProtoUnsafeBellatrix(st *ethpb.BeaconStateBellatrix) (state.B valMapHandler: stateutil.NewValMapHandler(st.Validators), } - if features.Get().EnableExperimentalState { - b.blockRootsMultiValue = NewMultiValueBlockRoots(st.BlockRoots) - b.stateRootsMultiValue = NewMultiValueStateRoots(st.StateRoots) - b.randaoMixesMultiValue = NewMultiValueRandaoMixes(st.RandaoMixes) - b.balancesMultiValue = NewMultiValueBalances(st.Balances) - b.validatorsMultiValue = NewMultiValueValidators(st.Validators) - b.inactivityScoresMultiValue = NewMultiValueInactivityScores(st.InactivityScores) - b.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, experimentalStateBellatrixSharedFieldRefCount) - } else { - bRoots := make([][32]byte, fieldparams.BlockRootsLength) - for i, r := range st.BlockRoots { - bRoots[i] = bytesutil.ToBytes32(r) - } - b.blockRoots = bRoots - - sRoots := make([][32]byte, fieldparams.StateRootsLength) - for i, r := range st.StateRoots { - sRoots[i] = bytesutil.ToBytes32(r) - } - b.stateRoots = sRoots - - mixes := make([][32]byte, fieldparams.RandaoMixesLength) - for i, m := range st.RandaoMixes { - mixes[i] = bytesutil.ToBytes32(m) - } - b.randaoMixes = mixes - - b.balances = st.Balances - b.validators = st.Validators - b.inactivityScores = st.InactivityScores - - b.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, bellatrixSharedFieldRefCount) - } + b.blockRootsMultiValue = NewMultiValueBlockRoots(st.BlockRoots) + b.stateRootsMultiValue = NewMultiValueStateRoots(st.StateRoots) + b.randaoMixesMultiValue = NewMultiValueRandaoMixes(st.RandaoMixes) + b.balancesMultiValue = NewMultiValueBalances(st.Balances) + b.validatorsMultiValue = NewMultiValueValidators(st.Validators) + b.inactivityScoresMultiValue = NewMultiValueInactivityScores(st.InactivityScores) + b.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, bellatrixSharedFieldRefCount) for _, f := range bellatrixFields { b.dirtyFields[f] = true @@ -476,14 +376,6 @@ func InitializeFromProtoUnsafeBellatrix(st *ethpb.BeaconStateBellatrix) (state.B b.sharedFieldReferences[types.PreviousEpochParticipationBits] = stateutil.NewRef(1) b.sharedFieldReferences[types.CurrentEpochParticipationBits] = stateutil.NewRef(1) b.sharedFieldReferences[types.LatestExecutionPayloadHeader] = stateutil.NewRef(1) // New in Bellatrix. - if !features.Get().EnableExperimentalState { - b.sharedFieldReferences[types.BlockRoots] = stateutil.NewRef(1) - b.sharedFieldReferences[types.StateRoots] = stateutil.NewRef(1) - b.sharedFieldReferences[types.RandaoMixes] = stateutil.NewRef(1) - b.sharedFieldReferences[types.Balances] = stateutil.NewRef(1) - b.sharedFieldReferences[types.Validators] = stateutil.NewRef(1) - b.sharedFieldReferences[types.InactivityScores] = stateutil.NewRef(1) - } state.Count.Inc() // Finalizer runs when dst is being destroyed in garbage collection. @@ -538,39 +430,13 @@ func InitializeFromProtoUnsafeCapella(st *ethpb.BeaconStateCapella) (state.Beaco valMapHandler: stateutil.NewValMapHandler(st.Validators), } - if features.Get().EnableExperimentalState { - b.blockRootsMultiValue = NewMultiValueBlockRoots(st.BlockRoots) - b.stateRootsMultiValue = NewMultiValueStateRoots(st.StateRoots) - b.randaoMixesMultiValue = NewMultiValueRandaoMixes(st.RandaoMixes) - b.balancesMultiValue = NewMultiValueBalances(st.Balances) - b.validatorsMultiValue = NewMultiValueValidators(st.Validators) - b.inactivityScoresMultiValue = NewMultiValueInactivityScores(st.InactivityScores) - b.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, experimentalStateCapellaSharedFieldRefCount) - } else { - bRoots := make([][32]byte, fieldparams.BlockRootsLength) - for i, r := range st.BlockRoots { - bRoots[i] = bytesutil.ToBytes32(r) - } - b.blockRoots = bRoots - - sRoots := make([][32]byte, fieldparams.StateRootsLength) - for i, r := range st.StateRoots { - sRoots[i] = bytesutil.ToBytes32(r) - } - b.stateRoots = sRoots - - mixes := make([][32]byte, fieldparams.RandaoMixesLength) - for i, m := range st.RandaoMixes { - mixes[i] = bytesutil.ToBytes32(m) - } - b.randaoMixes = mixes - - b.balances = st.Balances - b.validators = st.Validators - b.inactivityScores = st.InactivityScores - - b.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, capellaSharedFieldRefCount) - } + b.blockRootsMultiValue = NewMultiValueBlockRoots(st.BlockRoots) + b.stateRootsMultiValue = NewMultiValueStateRoots(st.StateRoots) + b.randaoMixesMultiValue = NewMultiValueRandaoMixes(st.RandaoMixes) + b.balancesMultiValue = NewMultiValueBalances(st.Balances) + b.validatorsMultiValue = NewMultiValueValidators(st.Validators) + b.inactivityScoresMultiValue = NewMultiValueInactivityScores(st.InactivityScores) + b.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, capellaSharedFieldRefCount) for _, f := range capellaFields { b.dirtyFields[f] = true @@ -591,14 +457,6 @@ func InitializeFromProtoUnsafeCapella(st *ethpb.BeaconStateCapella) (state.Beaco b.sharedFieldReferences[types.CurrentEpochParticipationBits] = stateutil.NewRef(1) b.sharedFieldReferences[types.LatestExecutionPayloadHeaderCapella] = stateutil.NewRef(1) // New in Capella. b.sharedFieldReferences[types.HistoricalSummaries] = stateutil.NewRef(1) // New in Capella. - if !features.Get().EnableExperimentalState { - b.sharedFieldReferences[types.BlockRoots] = stateutil.NewRef(1) - b.sharedFieldReferences[types.StateRoots] = stateutil.NewRef(1) - b.sharedFieldReferences[types.RandaoMixes] = stateutil.NewRef(1) - b.sharedFieldReferences[types.Balances] = stateutil.NewRef(1) - b.sharedFieldReferences[types.Validators] = stateutil.NewRef(1) - b.sharedFieldReferences[types.InactivityScores] = stateutil.NewRef(1) - } state.Count.Inc() // Finalizer runs when dst is being destroyed in garbage collection. @@ -651,39 +509,13 @@ func InitializeFromProtoUnsafeDeneb(st *ethpb.BeaconStateDeneb) (state.BeaconSta valMapHandler: stateutil.NewValMapHandler(st.Validators), } - if features.Get().EnableExperimentalState { - b.blockRootsMultiValue = NewMultiValueBlockRoots(st.BlockRoots) - b.stateRootsMultiValue = NewMultiValueStateRoots(st.StateRoots) - b.randaoMixesMultiValue = NewMultiValueRandaoMixes(st.RandaoMixes) - b.balancesMultiValue = NewMultiValueBalances(st.Balances) - b.validatorsMultiValue = NewMultiValueValidators(st.Validators) - b.inactivityScoresMultiValue = NewMultiValueInactivityScores(st.InactivityScores) - b.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, experimentalStateDenebSharedFieldRefCount) - } else { - bRoots := make([][32]byte, fieldparams.BlockRootsLength) - for i, r := range st.BlockRoots { - bRoots[i] = bytesutil.ToBytes32(r) - } - b.blockRoots = bRoots - - sRoots := make([][32]byte, fieldparams.StateRootsLength) - for i, r := range st.StateRoots { - sRoots[i] = bytesutil.ToBytes32(r) - } - b.stateRoots = sRoots - - mixes := make([][32]byte, fieldparams.RandaoMixesLength) - for i, m := range st.RandaoMixes { - mixes[i] = bytesutil.ToBytes32(m) - } - b.randaoMixes = mixes - - b.balances = st.Balances - b.validators = st.Validators - b.inactivityScores = st.InactivityScores - - b.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, denebSharedFieldRefCount) - } + b.blockRootsMultiValue = NewMultiValueBlockRoots(st.BlockRoots) + b.stateRootsMultiValue = NewMultiValueStateRoots(st.StateRoots) + b.randaoMixesMultiValue = NewMultiValueRandaoMixes(st.RandaoMixes) + b.balancesMultiValue = NewMultiValueBalances(st.Balances) + b.validatorsMultiValue = NewMultiValueValidators(st.Validators) + b.inactivityScoresMultiValue = NewMultiValueInactivityScores(st.InactivityScores) + b.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, denebSharedFieldRefCount) for _, f := range denebFields { b.dirtyFields[f] = true @@ -704,14 +536,6 @@ func InitializeFromProtoUnsafeDeneb(st *ethpb.BeaconStateDeneb) (state.BeaconSta b.sharedFieldReferences[types.CurrentEpochParticipationBits] = stateutil.NewRef(1) b.sharedFieldReferences[types.LatestExecutionPayloadHeaderDeneb] = stateutil.NewRef(1) // New in Deneb. b.sharedFieldReferences[types.HistoricalSummaries] = stateutil.NewRef(1) - if !features.Get().EnableExperimentalState { - b.sharedFieldReferences[types.BlockRoots] = stateutil.NewRef(1) - b.sharedFieldReferences[types.StateRoots] = stateutil.NewRef(1) - b.sharedFieldReferences[types.RandaoMixes] = stateutil.NewRef(1) - b.sharedFieldReferences[types.Balances] = stateutil.NewRef(1) - b.sharedFieldReferences[types.Validators] = stateutil.NewRef(1) - b.sharedFieldReferences[types.InactivityScores] = stateutil.NewRef(1) - } state.Count.Inc() // Finalizer runs when dst is being destroyed in garbage collection. @@ -773,39 +597,13 @@ func InitializeFromProtoUnsafeElectra(st *ethpb.BeaconStateElectra) (state.Beaco valMapHandler: stateutil.NewValMapHandler(st.Validators), } - if features.Get().EnableExperimentalState { - b.blockRootsMultiValue = NewMultiValueBlockRoots(st.BlockRoots) - b.stateRootsMultiValue = NewMultiValueStateRoots(st.StateRoots) - b.randaoMixesMultiValue = NewMultiValueRandaoMixes(st.RandaoMixes) - b.balancesMultiValue = NewMultiValueBalances(st.Balances) - b.validatorsMultiValue = NewMultiValueValidators(st.Validators) - b.inactivityScoresMultiValue = NewMultiValueInactivityScores(st.InactivityScores) - b.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, experimentalStateElectraSharedFieldRefCount) - } else { - bRoots := make([][32]byte, fieldparams.BlockRootsLength) - for i, r := range st.BlockRoots { - bRoots[i] = bytesutil.ToBytes32(r) - } - b.blockRoots = bRoots - - sRoots := make([][32]byte, fieldparams.StateRootsLength) - for i, r := range st.StateRoots { - sRoots[i] = bytesutil.ToBytes32(r) - } - b.stateRoots = sRoots - - mixes := make([][32]byte, fieldparams.RandaoMixesLength) - for i, m := range st.RandaoMixes { - mixes[i] = bytesutil.ToBytes32(m) - } - b.randaoMixes = mixes - - b.balances = st.Balances - b.validators = st.Validators - b.inactivityScores = st.InactivityScores - - b.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, electraSharedFieldRefCount) - } + b.blockRootsMultiValue = NewMultiValueBlockRoots(st.BlockRoots) + b.stateRootsMultiValue = NewMultiValueStateRoots(st.StateRoots) + b.randaoMixesMultiValue = NewMultiValueRandaoMixes(st.RandaoMixes) + b.balancesMultiValue = NewMultiValueBalances(st.Balances) + b.validatorsMultiValue = NewMultiValueValidators(st.Validators) + b.inactivityScoresMultiValue = NewMultiValueInactivityScores(st.InactivityScores) + b.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, electraSharedFieldRefCount) for _, f := range electraFields { b.dirtyFields[f] = true @@ -829,14 +627,6 @@ func InitializeFromProtoUnsafeElectra(st *ethpb.BeaconStateElectra) (state.Beaco b.sharedFieldReferences[types.PendingDeposits] = stateutil.NewRef(1) // New in Electra. b.sharedFieldReferences[types.PendingPartialWithdrawals] = stateutil.NewRef(1) // New in Electra. b.sharedFieldReferences[types.PendingConsolidations] = stateutil.NewRef(1) // New in Electra. - if !features.Get().EnableExperimentalState { - b.sharedFieldReferences[types.BlockRoots] = stateutil.NewRef(1) - b.sharedFieldReferences[types.StateRoots] = stateutil.NewRef(1) - b.sharedFieldReferences[types.RandaoMixes] = stateutil.NewRef(1) - b.sharedFieldReferences[types.Balances] = stateutil.NewRef(1) - b.sharedFieldReferences[types.Validators] = stateutil.NewRef(1) - b.sharedFieldReferences[types.InactivityScores] = stateutil.NewRef(1) - } state.Count.Inc() // Finalizer runs when dst is being destroyed in garbage collection. @@ -903,39 +693,13 @@ func InitializeFromProtoUnsafeFulu(st *ethpb.BeaconStateFulu) (state.BeaconState valMapHandler: stateutil.NewValMapHandler(st.Validators), } - if features.Get().EnableExperimentalState { - b.blockRootsMultiValue = NewMultiValueBlockRoots(st.BlockRoots) - b.stateRootsMultiValue = NewMultiValueStateRoots(st.StateRoots) - b.randaoMixesMultiValue = NewMultiValueRandaoMixes(st.RandaoMixes) - b.balancesMultiValue = NewMultiValueBalances(st.Balances) - b.validatorsMultiValue = NewMultiValueValidators(st.Validators) - b.inactivityScoresMultiValue = NewMultiValueInactivityScores(st.InactivityScores) - b.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, experimentalStateFuluSharedFieldRefCount) - } else { - bRoots := make([][32]byte, fieldparams.BlockRootsLength) - for i, r := range st.BlockRoots { - bRoots[i] = bytesutil.ToBytes32(r) - } - b.blockRoots = bRoots - - sRoots := make([][32]byte, fieldparams.StateRootsLength) - for i, r := range st.StateRoots { - sRoots[i] = bytesutil.ToBytes32(r) - } - b.stateRoots = sRoots - - mixes := make([][32]byte, fieldparams.RandaoMixesLength) - for i, m := range st.RandaoMixes { - mixes[i] = bytesutil.ToBytes32(m) - } - b.randaoMixes = mixes - - b.balances = st.Balances - b.validators = st.Validators - b.inactivityScores = st.InactivityScores - - b.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, fuluSharedFieldRefCount) - } + b.blockRootsMultiValue = NewMultiValueBlockRoots(st.BlockRoots) + b.stateRootsMultiValue = NewMultiValueStateRoots(st.StateRoots) + b.randaoMixesMultiValue = NewMultiValueRandaoMixes(st.RandaoMixes) + b.balancesMultiValue = NewMultiValueBalances(st.Balances) + b.validatorsMultiValue = NewMultiValueValidators(st.Validators) + b.inactivityScoresMultiValue = NewMultiValueInactivityScores(st.InactivityScores) + b.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, fuluSharedFieldRefCount) for _, f := range fuluFields { b.dirtyFields[f] = true @@ -960,14 +724,6 @@ func InitializeFromProtoUnsafeFulu(st *ethpb.BeaconStateFulu) (state.BeaconState b.sharedFieldReferences[types.PendingPartialWithdrawals] = stateutil.NewRef(1) b.sharedFieldReferences[types.PendingConsolidations] = stateutil.NewRef(1) b.sharedFieldReferences[types.ProposerLookahead] = stateutil.NewRef(1) // New in Fulu. - if !features.Get().EnableExperimentalState { - b.sharedFieldReferences[types.BlockRoots] = stateutil.NewRef(1) - b.sharedFieldReferences[types.StateRoots] = stateutil.NewRef(1) - b.sharedFieldReferences[types.RandaoMixes] = stateutil.NewRef(1) - b.sharedFieldReferences[types.Balances] = stateutil.NewRef(1) - b.sharedFieldReferences[types.Validators] = stateutil.NewRef(1) - b.sharedFieldReferences[types.InactivityScores] = stateutil.NewRef(1) - } state.Count.Inc() // Finalizer runs when dst is being destroyed in garbage collection. @@ -1015,11 +771,8 @@ func (b *BeaconState) Copy() state.BeaconState { earliestConsolidationEpoch: b.earliestConsolidationEpoch, // Large arrays, infrequently changed, constant size. - blockRoots: b.blockRoots, blockRootsMultiValue: b.blockRootsMultiValue, - stateRoots: b.stateRoots, stateRootsMultiValue: b.stateRootsMultiValue, - randaoMixes: b.randaoMixes, randaoMixesMultiValue: b.randaoMixesMultiValue, previousEpochAttestations: b.previousEpochAttestations, currentEpochAttestations: b.currentEpochAttestations, @@ -1028,15 +781,12 @@ func (b *BeaconState) Copy() state.BeaconState { proposerLookahead: b.proposerLookahead, // Large arrays, increases over time. - balances: b.balances, balancesMultiValue: b.balancesMultiValue, historicalRoots: b.historicalRoots, historicalSummaries: b.historicalSummaries, - validators: b.validators, validatorsMultiValue: b.validatorsMultiValue, previousEpochParticipation: b.previousEpochParticipation, currentEpochParticipation: b.currentEpochParticipation, - inactivityScores: b.inactivityScores, inactivityScoresMultiValue: b.inactivityScoresMultiValue, pendingDeposits: b.pendingDeposits, pendingPartialWithdrawals: b.pendingPartialWithdrawals, @@ -1068,51 +818,30 @@ func (b *BeaconState) Copy() state.BeaconState { valMapHandler: b.valMapHandler, } - if features.Get().EnableExperimentalState { - b.blockRootsMultiValue.Copy(b, dst) - b.stateRootsMultiValue.Copy(b, dst) - b.randaoMixesMultiValue.Copy(b, dst) - b.balancesMultiValue.Copy(b, dst) - if b.version > version.Phase0 { - b.inactivityScoresMultiValue.Copy(b, dst) - } - b.validatorsMultiValue.Copy(b, dst) + b.blockRootsMultiValue.Copy(b, dst) + b.stateRootsMultiValue.Copy(b, dst) + b.randaoMixesMultiValue.Copy(b, dst) + b.balancesMultiValue.Copy(b, dst) + if b.version > version.Phase0 { + b.inactivityScoresMultiValue.Copy(b, dst) } + b.validatorsMultiValue.Copy(b, dst) - if features.Get().EnableExperimentalState { - switch b.version { - case version.Phase0: - dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, experimentalStatePhase0SharedFieldRefCount) - case version.Altair: - dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, experimentalStateAltairSharedFieldRefCount) - case version.Bellatrix: - dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, experimentalStateBellatrixSharedFieldRefCount) - case version.Capella: - dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, experimentalStateCapellaSharedFieldRefCount) - case version.Deneb: - dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, experimentalStateDenebSharedFieldRefCount) - case version.Electra: - dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, experimentalStateElectraSharedFieldRefCount) - case version.Fulu: - dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, experimentalStateFuluSharedFieldRefCount) - } - } else { - switch b.version { - case version.Phase0: - dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, phase0SharedFieldRefCount) - case version.Altair: - dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, altairSharedFieldRefCount) - case version.Bellatrix: - dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, bellatrixSharedFieldRefCount) - case version.Capella: - dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, capellaSharedFieldRefCount) - case version.Deneb: - dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, denebSharedFieldRefCount) - case version.Electra: - dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, electraSharedFieldRefCount) - case version.Fulu: - dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, fuluSharedFieldRefCount) - } + switch b.version { + case version.Phase0: + dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, phase0SharedFieldRefCount) + case version.Altair: + dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, altairSharedFieldRefCount) + case version.Bellatrix: + dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, bellatrixSharedFieldRefCount) + case version.Capella: + dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, capellaSharedFieldRefCount) + case version.Deneb: + dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, denebSharedFieldRefCount) + case version.Electra: + dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, electraSharedFieldRefCount) + case version.Fulu: + dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, fuluSharedFieldRefCount) } for field, ref := range b.sharedFieldReferences { @@ -1256,10 +985,6 @@ func (b *BeaconState) FieldReferencesCount() map[string]uint64 { func (b *BeaconState) RecordStateMetrics() { b.lock.RLock() defer b.lock.RUnlock() - // Only run this for nodes running with the experimental state. - if !features.Get().EnableExperimentalState { - return - } // Validators if b.validatorsMultiValue != nil { @@ -1413,11 +1138,7 @@ func (b *BeaconState) rootSelector(ctx context.Context, field types.FieldIndex) case types.FinalizedCheckpoint: return ssz.CheckpointRoot(b.finalizedCheckpoint) case types.InactivityScores: - if features.Get().EnableExperimentalState { - return stateutil.Uint64ListRootWithRegistryLimit(b.inactivityScoresMultiValue.Value(b)) - } else { - return stateutil.Uint64ListRootWithRegistryLimit(b.inactivityScores) - } + return stateutil.Uint64ListRootWithRegistryLimit(b.inactivityScoresMultiValue.Value(b)) case types.CurrentSyncCommittee: return stateutil.SyncCommitteeRoot(b.currentSyncCommittee) case types.NextSyncCommittee: @@ -1561,25 +1282,23 @@ func finalizerCleanup(b *BeaconState) { delete(b.stateFieldLeaves, i) } - if features.Get().EnableExperimentalState { - if b.blockRootsMultiValue != nil { - b.blockRootsMultiValue.Detach(b) - } - if b.stateRootsMultiValue != nil { - b.stateRootsMultiValue.Detach(b) - } - if b.randaoMixesMultiValue != nil { - b.randaoMixesMultiValue.Detach(b) - } - if b.balancesMultiValue != nil { - b.balancesMultiValue.Detach(b) - } - if b.inactivityScoresMultiValue != nil { - b.inactivityScoresMultiValue.Detach(b) - } - if b.validatorsMultiValue != nil { - b.validatorsMultiValue.Detach(b) - } + if b.blockRootsMultiValue != nil { + b.blockRootsMultiValue.Detach(b) + } + if b.stateRootsMultiValue != nil { + b.stateRootsMultiValue.Detach(b) + } + if b.randaoMixesMultiValue != nil { + b.randaoMixesMultiValue.Detach(b) + } + if b.balancesMultiValue != nil { + b.balancesMultiValue.Detach(b) + } + if b.inactivityScoresMultiValue != nil { + b.inactivityScoresMultiValue.Detach(b) + } + if b.validatorsMultiValue != nil { + b.validatorsMultiValue.Detach(b) } state.Count.Sub(1) @@ -1587,145 +1306,94 @@ func finalizerCleanup(b *BeaconState) { func (b *BeaconState) blockRootsRootSelector(field types.FieldIndex) ([32]byte, error) { if b.rebuildTrie[field] { - if features.Get().EnableExperimentalState { - err := b.resetFieldTrie(field, mvslice.MultiValueSliceComposite[[32]byte]{ - Identifiable: b, - MultiValueSlice: b.blockRootsMultiValue, - }, fieldparams.BlockRootsLength) - if err != nil { - return [32]byte{}, err - } - } else { - err := b.resetFieldTrie(field, b.blockRoots, fieldparams.BlockRootsLength) - if err != nil { - return [32]byte{}, err - } + err := b.resetFieldTrie(field, mvslice.MultiValueSliceComposite[[32]byte]{ + Identifiable: b, + MultiValueSlice: b.blockRootsMultiValue, + }, fieldparams.BlockRootsLength) + if err != nil { + return [32]byte{}, err } + delete(b.rebuildTrie, field) return b.stateFieldLeaves[field].TrieRoot() } - if features.Get().EnableExperimentalState { - return b.recomputeFieldTrie(field, mvslice.MultiValueSliceComposite[[32]byte]{ - Identifiable: b, - MultiValueSlice: b.blockRootsMultiValue, - }) - } else { - return b.recomputeFieldTrie(field, b.blockRoots) - } + return b.recomputeFieldTrie(field, mvslice.MultiValueSliceComposite[[32]byte]{ + Identifiable: b, + MultiValueSlice: b.blockRootsMultiValue, + }) } func (b *BeaconState) stateRootsRootSelector(field types.FieldIndex) ([32]byte, error) { if b.rebuildTrie[field] { - if features.Get().EnableExperimentalState { - err := b.resetFieldTrie(field, mvslice.MultiValueSliceComposite[[32]byte]{ - Identifiable: b, - MultiValueSlice: b.stateRootsMultiValue, - }, fieldparams.StateRootsLength) - if err != nil { - return [32]byte{}, err - } - } else { - err := b.resetFieldTrie(field, b.stateRoots, fieldparams.StateRootsLength) - if err != nil { - return [32]byte{}, err - } + err := b.resetFieldTrie(field, mvslice.MultiValueSliceComposite[[32]byte]{ + Identifiable: b, + MultiValueSlice: b.stateRootsMultiValue, + }, fieldparams.StateRootsLength) + if err != nil { + return [32]byte{}, err } + delete(b.rebuildTrie, field) return b.stateFieldLeaves[field].TrieRoot() } - if features.Get().EnableExperimentalState { - return b.recomputeFieldTrie(field, mvslice.MultiValueSliceComposite[[32]byte]{ - Identifiable: b, - MultiValueSlice: b.stateRootsMultiValue, - }) - } else { - return b.recomputeFieldTrie(field, b.stateRoots) - } + return b.recomputeFieldTrie(field, mvslice.MultiValueSliceComposite[[32]byte]{ + Identifiable: b, + MultiValueSlice: b.stateRootsMultiValue, + }) } func (b *BeaconState) validatorsRootSelector(field types.FieldIndex) ([32]byte, error) { if b.rebuildTrie[field] { - if features.Get().EnableExperimentalState { - err := b.resetFieldTrie(field, mvslice.MultiValueSliceComposite[*ethpb.Validator]{ - Identifiable: b, - MultiValueSlice: b.validatorsMultiValue, - }, fieldparams.ValidatorRegistryLimit) - if err != nil { - return [32]byte{}, err - } - } else { - err := b.resetFieldTrie(field, b.validators, fieldparams.ValidatorRegistryLimit) - if err != nil { - return [32]byte{}, err - } + err := b.resetFieldTrie(field, mvslice.MultiValueSliceComposite[*ethpb.Validator]{ + Identifiable: b, + MultiValueSlice: b.validatorsMultiValue, + }, fieldparams.ValidatorRegistryLimit) + if err != nil { + return [32]byte{}, err } + delete(b.rebuildTrie, field) return b.stateFieldLeaves[field].TrieRoot() } - if features.Get().EnableExperimentalState { - return b.recomputeFieldTrie(field, mvslice.MultiValueSliceComposite[*ethpb.Validator]{ - Identifiable: b, - MultiValueSlice: b.validatorsMultiValue, - }) - } else { - return b.recomputeFieldTrie(field, b.validators) - } + return b.recomputeFieldTrie(field, mvslice.MultiValueSliceComposite[*ethpb.Validator]{ + Identifiable: b, + MultiValueSlice: b.validatorsMultiValue, + }) } func (b *BeaconState) balancesRootSelector(field types.FieldIndex) ([32]byte, error) { if b.rebuildTrie[field] { - if features.Get().EnableExperimentalState { - err := b.resetFieldTrie(field, mvslice.MultiValueSliceComposite[uint64]{ - Identifiable: b, - MultiValueSlice: b.balancesMultiValue, - }, stateutil.ValidatorLimitForBalancesChunks()) - if err != nil { - return [32]byte{}, err - } - } else { - err := b.resetFieldTrie(field, b.balances, stateutil.ValidatorLimitForBalancesChunks()) - if err != nil { - return [32]byte{}, err - } + err := b.resetFieldTrie(field, mvslice.MultiValueSliceComposite[uint64]{ + Identifiable: b, + MultiValueSlice: b.balancesMultiValue, + }, stateutil.ValidatorLimitForBalancesChunks()) + if err != nil { + return [32]byte{}, err } delete(b.rebuildTrie, field) return b.stateFieldLeaves[field].TrieRoot() } - if features.Get().EnableExperimentalState { - return b.recomputeFieldTrie(field, mvslice.MultiValueSliceComposite[uint64]{ - Identifiable: b, - MultiValueSlice: b.balancesMultiValue, - }) - } else { - return b.recomputeFieldTrie(field, b.balances) - } + return b.recomputeFieldTrie(field, mvslice.MultiValueSliceComposite[uint64]{ + Identifiable: b, + MultiValueSlice: b.balancesMultiValue, + }) } func (b *BeaconState) randaoMixesRootSelector(field types.FieldIndex) ([32]byte, error) { if b.rebuildTrie[field] { - if features.Get().EnableExperimentalState { - err := b.resetFieldTrie(field, mvslice.MultiValueSliceComposite[[32]byte]{ - Identifiable: b, - MultiValueSlice: b.randaoMixesMultiValue, - }, fieldparams.RandaoMixesLength) - if err != nil { - return [32]byte{}, err - } - } else { - err := b.resetFieldTrie(field, b.randaoMixes, fieldparams.RandaoMixesLength) - if err != nil { - return [32]byte{}, err - } + err := b.resetFieldTrie(field, mvslice.MultiValueSliceComposite[[32]byte]{ + Identifiable: b, + MultiValueSlice: b.randaoMixesMultiValue, + }, fieldparams.RandaoMixesLength) + if err != nil { + return [32]byte{}, err } + delete(b.rebuildTrie, field) return b.stateFieldLeaves[field].TrieRoot() } - if features.Get().EnableExperimentalState { - return b.recomputeFieldTrie(field, mvslice.MultiValueSliceComposite[[32]byte]{ - Identifiable: b, - MultiValueSlice: b.randaoMixesMultiValue, - }) - } else { - return b.recomputeFieldTrie(field, b.randaoMixes) - } + return b.recomputeFieldTrie(field, mvslice.MultiValueSliceComposite[[32]byte]{ + Identifiable: b, + MultiValueSlice: b.randaoMixesMultiValue, + }) } diff --git a/beacon-chain/state/state-native/state_trie_test.go b/beacon-chain/state/state-native/state_trie_test.go index e45459727f..bbc7043c5c 100644 --- a/beacon-chain/state/state-native/state_trie_test.go +++ b/beacon-chain/state/state-native/state_trie_test.go @@ -6,7 +6,6 @@ import ( "github.com/OffchainLabs/prysm/v6/beacon-chain/state" statenative "github.com/OffchainLabs/prysm/v6/beacon-chain/state/state-native" - "github.com/OffchainLabs/prysm/v6/config/features" "github.com/OffchainLabs/prysm/v6/config/params" "github.com/OffchainLabs/prysm/v6/encoding/bytesutil" ethpb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1" @@ -805,10 +804,6 @@ func TestBeaconState_ValidatorMutation_Bellatrix(t *testing.T) { } func TestBeaconState_InitializeInactivityScoresCorrectly_Deneb(t *testing.T) { - resetCfg := features.InitWithReset(&features.Flags{ - EnableExperimentalState: true, - }) - defer resetCfg() st, _ := util.DeterministicGenesisStateDeneb(t, 200) _, err := st.HashTreeRoot(t.Context()) require.NoError(t, err) diff --git a/beacon-chain/state/testing/getters_validator.go b/beacon-chain/state/testing/getters_validator.go index 5fda630a64..0f411ae862 100644 --- a/beacon-chain/state/testing/getters_validator.go +++ b/beacon-chain/state/testing/getters_validator.go @@ -15,5 +15,5 @@ func VerifyBeaconStateValidatorAtIndexReadOnlyHandlesNilSlice(t *testing.T, fact require.NoError(t, err) _, err = st.ValidatorAtIndexReadOnly(0) - assert.Equal(t, state.ErrNilValidatorsInState, err) + assert.ErrorContains(t, "index 0 out of bounds", err) } diff --git a/changelog/nisdas_mv_slice_permanent.md b/changelog/nisdas_mv_slice_permanent.md new file mode 100644 index 0000000000..ebe7937f76 --- /dev/null +++ b/changelog/nisdas_mv_slice_permanent.md @@ -0,0 +1,3 @@ +### Changed + +- Makes the multivalue slice permanent in the state and removes old paths. \ No newline at end of file diff --git a/config/features/config.go b/config/features/config.go index edd84f72f9..b7ec21289f 100644 --- a/config/features/config.go +++ b/config/features/config.go @@ -40,7 +40,6 @@ const disabledFeatureFlag = "Disabled feature flag" // Flags is a struct to represent which features the client will perform on runtime. type Flags struct { // Feature related flags. - EnableExperimentalState bool // EnableExperimentalState turns on the latest and greatest (but potentially unstable) changes to the beacon state. WriteSSZStateTransitions bool // WriteSSZStateTransitions to tmp directory. EnablePeerScorer bool // EnablePeerScorer enables experimental peer scoring in p2p. EnableLightClient bool // EnableLightClient enables light client APIs. @@ -189,12 +188,6 @@ func ConfigureBeaconChain(ctx *cli.Context) error { return err } - cfg.EnableExperimentalState = true - if ctx.Bool(disableExperimentalState.Name) { - logEnabled(disableExperimentalState) - cfg.EnableExperimentalState = false - } - if ctx.Bool(writeSSZStateTransitionsFlag.Name) { logEnabled(writeSSZStateTransitionsFlag) cfg.WriteSSZStateTransitions = true diff --git a/config/features/deprecated_flags.go b/config/features/deprecated_flags.go index 501c981776..6c6d6b22ba 100644 --- a/config/features/deprecated_flags.go +++ b/config/features/deprecated_flags.go @@ -103,6 +103,11 @@ var ( Usage: deprecatedUsage, Hidden: true, } + deprecatedDisableExperimentalState = &cli.BoolFlag{ + Name: "disable-experimental-state", + Usage: deprecatedUsage, + Hidden: true, + } ) // Deprecated flags for both the beacon node and validator client. @@ -124,6 +129,7 @@ var deprecatedFlags = []cli.Flag{ deprecatedInteropGenesisTimeFlag, deprecatedEnableQuic, deprecatedAttestTimely, + deprecatedDisableExperimentalState, } var upcomingDeprecation = []cli.Flag{ diff --git a/config/features/flags.go b/config/features/flags.go index f5f947348e..df055af5c8 100644 --- a/config/features/flags.go +++ b/config/features/flags.go @@ -33,10 +33,6 @@ var ( Name: "dev", Usage: "Enables experimental features still in development. These features may not be stable.", } - disableExperimentalState = &cli.BoolFlag{ - Name: "disable-experimental-state", - Usage: "Turns off the latest and greatest changes to the beacon state. Disabling this is safe to do after the feature has been enabled.", - } writeSSZStateTransitionsFlag = &cli.BoolFlag{ Name: "interop-write-ssz-state-transitions", Usage: "Writes SSZ states to disk after attempted state transitio.", @@ -240,7 +236,6 @@ var E2EValidatorFlags = []string{ // BeaconChainFlags contains a list of all the feature flags that apply to the beacon-chain client. var BeaconChainFlags = combinedFlags([]cli.Flag{ devModeFlag, - disableExperimentalState, writeSSZStateTransitionsFlag, saveInvalidBlockTempFlag, saveInvalidBlobTempFlag, diff --git a/consensus-types/types.go b/consensus-types/types.go index a94b4aa2a1..5b5054d3fe 100644 --- a/consensus-types/types.go +++ b/consensus-types/types.go @@ -15,7 +15,6 @@ var ( // ErrUnsupportedField is returned when a getter/setter access is not supported. ErrUnsupportedField = errors.New("unsupported getter") // ErrOutOfBounds is returned when a slice or array index does not exist. - ErrOutOfBounds = errors.New("index out of bounds") ) // ErrNotSupported constructs a message informing about an unsupported field access. diff --git a/container/multi-value-slice/multi_value_slice.go b/container/multi-value-slice/multi_value_slice.go index 683ec41f5e..5c33535713 100644 --- a/container/multi-value-slice/multi_value_slice.go +++ b/container/multi-value-slice/multi_value_slice.go @@ -101,6 +101,9 @@ import ( // fragmented. const fragmentationLimit = 50000 +// ErrOutOfBounds happens when the provided index is higher than the largest index of the slice. +var ErrOutOfBounds = errors.New("out of bounds") + // Id is an object identifier. type Id = uint64 @@ -255,7 +258,7 @@ func (s *Slice[V]) At(obj Identifiable, index uint64) (V, error) { if index >= uint64(len(s.sharedItems)+len(s.appendedItems)) { var def V - return def, fmt.Errorf("index %d out of bounds", index) + return def, fmt.Errorf("index %d %w", index, ErrOutOfBounds) } isOriginal := index < uint64(len(s.sharedItems)) @@ -282,7 +285,7 @@ func (s *Slice[V]) At(obj Identifiable, index uint64) (V, error) { } } var def V - return def, fmt.Errorf("index %d out of bounds", index) + return def, fmt.Errorf("index %d %w", index, ErrOutOfBounds) } } @@ -292,7 +295,7 @@ func (s *Slice[V]) UpdateAt(obj Identifiable, index uint64, val V) error { defer s.lock.Unlock() if index >= uint64(len(s.sharedItems)+len(s.appendedItems)) { - return fmt.Errorf("index %d out of bounds", index) + return fmt.Errorf("index %d %w", index, ErrOutOfBounds) } isOriginal := index < uint64(len(s.sharedItems)) @@ -560,7 +563,7 @@ func (s *Slice[V]) updateAppendedItem(obj Identifiable, index uint64, val V) err } } if !found { - return fmt.Errorf("index %d out of bounds", index) + return fmt.Errorf("index %d %w", index, ErrOutOfBounds) } newValue := true @@ -606,7 +609,7 @@ func (e EmptyMVSlice[V]) Len(_ Identifiable) int { func (e EmptyMVSlice[V]) At(_ Identifiable, index uint64) (V, error) { if index >= uint64(len(e.fullSlice)) { var def V - return def, errors.Errorf("index %d out of bounds", index) + return def, fmt.Errorf("index %d %w", index, ErrOutOfBounds) } return e.fullSlice[index], nil } diff --git a/container/multi-value-slice/multi_value_slice_test.go b/container/multi-value-slice/multi_value_slice_test.go index 44be459df4..c8f6a94a45 100644 --- a/container/multi-value-slice/multi_value_slice_test.go +++ b/container/multi-value-slice/multi_value_slice_test.go @@ -476,6 +476,20 @@ func TestFragmentation_IndividualAndAppendedReferences(t *testing.T) { assert.Equal(t, true, s.IsFragmented()) } +func TestNil(t *testing.T) { + obj := &testObject{} + + s := &Slice[int]{} + s.Init(nil) + assert.Equal(t, 0, s.Len(obj)) + assert.DeepEqual(t, []int{}, s.Value(obj)) + _, err := s.At(obj, 0) + assert.NotNil(t, err) + s.Append(obj, 1) + assert.Equal(t, 1, s.Len(obj)) + assert.DeepEqual(t, []int{1}, s.Value(obj)) +} + // Share the slice between 2 objects. // Index 0: Shared value // Index 1: Different individual value diff --git a/testing/fuzz/fuzz.go b/testing/fuzz/fuzz.go index 3a8c3c863b..965f3e8013 100644 --- a/testing/fuzz/fuzz.go +++ b/testing/fuzz/fuzz.go @@ -3,13 +3,13 @@ package fuzz import "runtime/debug" // FreeMemory calls debug.FreeOSMemory() every 10 loop iterations. -// This is very useful in tests that fuzz a proto beacon state -// and initialize a native state from that proto state inside the loop. +// This is very useful in tests that initialize a native state from a proto state inside a loop. +// Most commonly this happens in tests that make use of fuzzing. // The reason is that fields of the native beacon state which are multi-value // slices always create a slice of proper length for that field, even if -// the fuzzer creates a smaller slice. Because the beacon state keeps -// a reference to the multi-value slice, the multi-value slice is not garbage -// collected fast enough during fuzzing, leading to memory bloat. +// the proto state's slice has a smaller length. Because the beacon state keeps +// a reference to the multi-value slice object, the multi-value slice is not garbage +// collected fast enough, leading to memory bloat. // Freeing memory manually every 10 iterations keeps the in-use memory low. // The tradeoff is longer test times. func FreeMemory(iteration int) {