mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-08 23:18:15 -05:00
Make the multi-value slice permanent (#15414)
* Remove Old State Paths * Changelog * Gazelle * Lint * Fix State Tests * fix tests, update native state code * move ErrOutOfBounds error from consensus types to mvslice * fix TestStreamEvents_OperationsEvents * add missing gc to fuzz tests * more test fixes * build fix --------- Co-authored-by: nisdas <nishdas93@gmail.com>
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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).
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()))
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
3
changelog/nisdas_mv_slice_permanent.md
Normal file
3
changelog/nisdas_mv_slice_permanent.md
Normal file
@@ -0,0 +1,3 @@
|
||||
### Changed
|
||||
|
||||
- Makes the multivalue slice permanent in the state and removes old paths.
|
||||
@@ -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
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user