diff --git a/beacon-chain/core/epoch/precompute/justification_finalization.go b/beacon-chain/core/epoch/precompute/justification_finalization.go index 1c71d23363..0f19cdb67f 100644 --- a/beacon-chain/core/epoch/precompute/justification_finalization.go +++ b/beacon-chain/core/epoch/precompute/justification_finalization.go @@ -106,7 +106,7 @@ func weighJustificationAndFinalization(state state.BeaconState, if err := state.SetCurrentJustifiedCheckpoint(ðpb.Checkpoint{Epoch: prevEpoch, Root: blockRoot}); err != nil { return nil, err } - newBits := state.JustificationBits() + newBits = state.JustificationBits() newBits.SetBitAt(1, true) if err := state.SetJustificationBits(newBits); err != nil { return nil, err @@ -122,7 +122,7 @@ func weighJustificationAndFinalization(state state.BeaconState, if err := state.SetCurrentJustifiedCheckpoint(ðpb.Checkpoint{Epoch: currentEpoch, Root: blockRoot}); err != nil { return nil, err } - newBits := state.JustificationBits() + newBits = state.JustificationBits() newBits.SetBitAt(0, true) if err := state.SetJustificationBits(newBits); err != nil { return nil, err diff --git a/beacon-chain/db/kv/BUILD.bazel b/beacon-chain/db/kv/BUILD.bazel index bdb627e617..c079664494 100644 --- a/beacon-chain/db/kv/BUILD.bazel +++ b/beacon-chain/db/kv/BUILD.bazel @@ -40,6 +40,7 @@ go_library( "//beacon-chain/db/iface:go_default_library", "//beacon-chain/state:go_default_library", "//beacon-chain/state/genesis:go_default_library", + "//beacon-chain/state/state-native:go_default_library", "//beacon-chain/state/v1:go_default_library", "//beacon-chain/state/v2:go_default_library", "//beacon-chain/state/v3:go_default_library", diff --git a/beacon-chain/db/kv/state.go b/beacon-chain/db/kv/state.go index 78baa45ccf..e606fe4677 100644 --- a/beacon-chain/db/kv/state.go +++ b/beacon-chain/db/kv/state.go @@ -10,6 +10,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/state" "github.com/prysmaticlabs/prysm/beacon-chain/state/genesis" + state_native "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native" v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" v2 "github.com/prysmaticlabs/prysm/beacon-chain/state/v2" v3 "github.com/prysmaticlabs/prysm/beacon-chain/state/v3" @@ -204,7 +205,13 @@ func (s *Store) SaveStatesEfficient(ctx context.Context, states []state.ReadOnly // look at issue https://github.com/prysmaticlabs/prysm/issues/9262. switch rawType := states[i].InnerStateUnsafe().(type) { case *ethpb.BeaconState: - pbState, err := v1.ProtobufBeaconState(rawType) + var pbState *ethpb.BeaconState + var err error + if features.Get().EnableNativeState { + pbState, err = state_native.ProtobufBeaconStatePhase0(rawType) + } else { + pbState, err = v1.ProtobufBeaconState(rawType) + } if err != nil { return err } @@ -225,7 +232,13 @@ func (s *Store) SaveStatesEfficient(ctx context.Context, states []state.ReadOnly return err } case *ethpb.BeaconStateAltair: - pbState, err := v2.ProtobufBeaconState(rawType) + var pbState *ethpb.BeaconStateAltair + var err error + if features.Get().EnableNativeState { + pbState, err = state_native.ProtobufBeaconStateAltair(rawType) + } else { + pbState, err = v2.ProtobufBeaconState(rawType) + } if err != nil { return err } @@ -247,7 +260,13 @@ func (s *Store) SaveStatesEfficient(ctx context.Context, states []state.ReadOnly return err } case *ethpb.BeaconStateBellatrix: - pbState, err := v3.ProtobufBeaconState(rawType) + var pbState *ethpb.BeaconStateBellatrix + var err error + if features.Get().EnableNativeState { + pbState, err = state_native.ProtobufBeaconStateBellatrix(rawType) + } else { + pbState, err = v3.ProtobufBeaconState(rawType) + } if err != nil { return err } @@ -274,28 +293,7 @@ func (s *Store) SaveStatesEfficient(ctx context.Context, states []state.ReadOnly } // store the validator entries separately to save space. - valBkt := tx.Bucket(stateValidatorsBucket) - for hashStr, validatorEntry := range validatorsEntries { - key := []byte(hashStr) - // if the entry is not in the cache and not in the DB, - // then insert it in the DB and add to the cache. - if _, ok := s.validatorEntryCache.Get(key); !ok { - validatorEntryCacheMiss.Inc() - if valEntry := valBkt.Get(key); valEntry == nil { - valBytes, encodeErr := encode(ctx, validatorEntry) - if encodeErr != nil { - return encodeErr - } - if putErr := valBkt.Put(key, valBytes); putErr != nil { - return putErr - } - s.validatorEntryCache.Set(key, validatorEntry, int64(len(valBytes))) - } - } else { - validatorEntryCacheHit.Inc() - } - } - return nil + return s.storeValidatorEntriesSeparately(ctx, tx, validatorsEntries) }); err != nil { return err } @@ -303,6 +301,31 @@ func (s *Store) SaveStatesEfficient(ctx context.Context, states []state.ReadOnly return nil } +func (s *Store) storeValidatorEntriesSeparately(ctx context.Context, tx *bolt.Tx, validatorsEntries map[string]*ethpb.Validator) error { + valBkt := tx.Bucket(stateValidatorsBucket) + for hashStr, validatorEntry := range validatorsEntries { + key := []byte(hashStr) + // if the entry is not in the cache and not in the DB, + // then insert it in the DB and add to the cache. + if _, ok := s.validatorEntryCache.Get(key); !ok { + validatorEntryCacheMiss.Inc() + if valEntry := valBkt.Get(key); valEntry == nil { + valBytes, encodeErr := encode(ctx, validatorEntry) + if encodeErr != nil { + return encodeErr + } + if putErr := valBkt.Put(key, valBytes); putErr != nil { + return putErr + } + s.validatorEntryCache.Set(key, validatorEntry, int64(len(valBytes))) + } + } else { + validatorEntryCacheHit.Inc() + } + } + return nil +} + // HasState checks if a state by root exists in the db. func (s *Store) HasState(ctx context.Context, blockRoot [32]byte) bool { _, span := trace.StartSpan(ctx, "BeaconDB.HasState") diff --git a/beacon-chain/powchain/BUILD.bazel b/beacon-chain/powchain/BUILD.bazel index d628634063..c023c483a6 100644 --- a/beacon-chain/powchain/BUILD.bazel +++ b/beacon-chain/powchain/BUILD.bazel @@ -34,7 +34,7 @@ go_library( "//beacon-chain/db:go_default_library", "//beacon-chain/powchain/types:go_default_library", "//beacon-chain/state:go_default_library", - "//beacon-chain/state/state-native/v1:go_default_library", + "//beacon-chain/state/state-native:go_default_library", "//beacon-chain/state/stategen:go_default_library", "//beacon-chain/state/v1:go_default_library", "//config/features:go_default_library", diff --git a/beacon-chain/powchain/log_processing.go b/beacon-chain/powchain/log_processing.go index a4a90672b6..160bc41c80 100644 --- a/beacon-chain/powchain/log_processing.go +++ b/beacon-chain/powchain/log_processing.go @@ -17,7 +17,9 @@ import ( statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" coreState "github.com/prysmaticlabs/prysm/beacon-chain/core/transition" + state_native "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native" v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + "github.com/prysmaticlabs/prysm/config/features" "github.com/prysmaticlabs/prysm/config/params" contracts "github.com/prysmaticlabs/prysm/contracts/deposit" "github.com/prysmaticlabs/prysm/crypto/hash" @@ -516,7 +518,13 @@ func (s *Service) checkForChainstart(ctx context.Context, blockHash [32]byte, bl // save all powchain related metadata to disk. func (s *Service) savePowchainData(ctx context.Context) error { - pbState, err := v1.ProtobufBeaconState(s.preGenesisState.InnerStateUnsafe()) + var pbState *ethpb.BeaconState + var err error + if features.Get().EnableNativeState { + pbState, err = state_native.ProtobufBeaconStatePhase0(s.preGenesisState.InnerStateUnsafe()) + } else { + pbState, err = v1.ProtobufBeaconState(s.preGenesisState.InnerStateUnsafe()) + } if err != nil { return err } diff --git a/beacon-chain/powchain/service.go b/beacon-chain/powchain/service.go index 0e8696e863..4ea77d2e3f 100644 --- a/beacon-chain/powchain/service.go +++ b/beacon-chain/powchain/service.go @@ -30,7 +30,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/db" "github.com/prysmaticlabs/prysm/beacon-chain/powchain/types" "github.com/prysmaticlabs/prysm/beacon-chain/state" - nativev1 "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/v1" + native "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native" "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" "github.com/prysmaticlabs/prysm/config/features" @@ -273,7 +273,7 @@ func (s *Service) Stop() error { func (s *Service) ClearPreGenesisData() { s.chainStartData.ChainstartDeposits = []*ethpb.Deposit{} if features.Get().EnableNativeState { - s.preGenesisState = &nativev1.BeaconState{} + s.preGenesisState = &native.BeaconState{} } else { s.preGenesisState = &v1.BeaconState{} } @@ -830,7 +830,13 @@ func (s *Service) ensureValidPowchainData(ctx context.Context) error { return errors.Wrap(err, "unable to retrieve eth1 data") } if eth1Data == nil || !eth1Data.ChainstartData.Chainstarted || !validateDepositContainers(eth1Data.DepositContainers) { - pbState, err := v1.ProtobufBeaconState(s.preGenesisState.InnerStateUnsafe()) + var pbState *ethpb.BeaconState + var err error + if features.Get().EnableNativeState { + pbState, err = native.ProtobufBeaconStatePhase0(s.preGenesisState.InnerStateUnsafe()) + } else { + pbState, err = v1.ProtobufBeaconState(s.preGenesisState.InnerStateUnsafe()) + } if err != nil { return err } diff --git a/beacon-chain/state/fieldtrie/BUILD.bazel b/beacon-chain/state/fieldtrie/BUILD.bazel index 2a8ca97c27..04f06153e3 100644 --- a/beacon-chain/state/fieldtrie/BUILD.bazel +++ b/beacon-chain/state/fieldtrie/BUILD.bazel @@ -10,6 +10,7 @@ go_library( visibility = ["//beacon-chain:__subpackages__"], deps = [ "//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", "//beacon-chain/state/types:go_default_library", "//crypto/hash:go_default_library", diff --git a/beacon-chain/state/fieldtrie/field_trie.go b/beacon-chain/state/fieldtrie/field_trie.go index 040a37d65f..62a713477c 100644 --- a/beacon-chain/state/fieldtrie/field_trie.go +++ b/beacon-chain/state/fieldtrie/field_trie.go @@ -16,7 +16,7 @@ type FieldTrie struct { *sync.RWMutex reference *stateutil.Reference fieldLayers [][]*[32]byte - field types.FieldIndex + field types.BeaconStateField dataType types.DataType length uint64 numOfElems int @@ -25,7 +25,7 @@ type FieldTrie struct { // NewFieldTrie is the constructor for the field trie data structure. It creates the corresponding // trie according to the given parameters. Depending on whether the field is a basic/composite array // which is either fixed/variable length, it will appropriately determine the trie. -func NewFieldTrie(field types.FieldIndex, dataType types.DataType, elements interface{}, length uint64) (*FieldTrie, error) { +func NewFieldTrie(field types.BeaconStateField, dataType types.DataType, elements interface{}, length uint64) (*FieldTrie, error) { if elements == nil { return &FieldTrie{ field: field, @@ -36,10 +36,19 @@ func NewFieldTrie(field types.FieldIndex, dataType types.DataType, elements inte numOfElems: 0, }, nil } - fieldRoots, err := fieldConverters(field, []uint64{}, elements, true) + + var fieldRoots [][32]byte + var err error + if field.Native() { + fieldRoots, err = fieldConvertersNative(field, []uint64{}, elements, true) + } else { + fieldRoots, err = fieldConverters(field, []uint64{}, elements, true) + } + if err != nil { return nil, err } + if err := validateElements(field, dataType, elements, length); err != nil { return nil, err } @@ -84,10 +93,18 @@ func (f *FieldTrie) RecomputeTrie(indices []uint64, elements interface{}) ([32]b if len(indices) == 0 { return f.TrieRoot() } - fieldRoots, err := fieldConverters(f.field, indices, elements, false) + + var fieldRoots [][32]byte + var err error + if f.field.Native() { + fieldRoots, err = fieldConvertersNative(f.field, indices, elements, false) + } else { + fieldRoots, err = fieldConverters(f.field, indices, elements, false) + } if err != nil { return [32]byte{}, err } + if err := f.validateIndices(indices); err != nil { return [32]byte{}, err } diff --git a/beacon-chain/state/fieldtrie/field_trie_helpers.go b/beacon-chain/state/fieldtrie/field_trie_helpers.go index d3ef27016f..63afe34feb 100644 --- a/beacon-chain/state/fieldtrie/field_trie_helpers.go +++ b/beacon-chain/state/fieldtrie/field_trie_helpers.go @@ -7,6 +7,7 @@ import ( "github.com/pkg/errors" customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types" + nativetypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/types" "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" "github.com/prysmaticlabs/prysm/beacon-chain/state/types" "github.com/prysmaticlabs/prysm/crypto/hash" @@ -18,7 +19,7 @@ import ( ) // ProofFromMerkleLayers creates a proof starting at the leaf index of the state Merkle layers. -func ProofFromMerkleLayers(layers [][][]byte, startingLeafIndex types.FieldIndex) [][]byte { +func ProofFromMerkleLayers(layers [][][]byte, startingLeafIndex int) [][]byte { // The merkle tree structure looks as follows: // [[r1, r2, r3, r4], [parent1, parent2], [root]] proof := make([][]byte, 0) @@ -49,7 +50,7 @@ func (f *FieldTrie) validateIndices(idxs []uint64) error { return nil } -func validateElements(field types.FieldIndex, dataType types.DataType, elements interface{}, length uint64) error { +func validateElements(field types.BeaconStateField, dataType types.DataType, elements interface{}, length uint64) error { if dataType == types.CompressedArray { comLength, err := field.ElemsInChunk() if err != nil { @@ -65,68 +66,118 @@ func validateElements(field types.FieldIndex, dataType types.DataType, elements } // fieldConverters converts the corresponding field and the provided elements to the appropriate roots. -func fieldConverters(field types.FieldIndex, indices []uint64, elements interface{}, convertAll bool) ([][32]byte, error) { +func fieldConverters(field types.BeaconStateField, indices []uint64, elements interface{}, convertAll bool) ([][32]byte, error) { switch field { case types.BlockRoots: - switch val := elements.(type) { - case [][]byte: - return handleByteArrays(val, indices, convertAll) - case *customtypes.BlockRoots: - return handle32ByteArrays(val[:], indices, convertAll) - default: - return nil, errors.Errorf("Incorrect type used for block roots") - } + return convertBlockRoots(indices, elements, convertAll) case types.StateRoots: - switch val := elements.(type) { - case [][]byte: - return handleByteArrays(val, indices, convertAll) - case *customtypes.StateRoots: - return handle32ByteArrays(val[:], indices, convertAll) - default: - return nil, errors.Errorf("Incorrect type used for state roots") - } + return convertStateRoots(indices, elements, convertAll) case types.RandaoMixes: - switch val := elements.(type) { - case [][]byte: - return handleByteArrays(val, indices, convertAll) - case *customtypes.RandaoMixes: - return handle32ByteArrays(val[:], indices, convertAll) - default: - return nil, errors.Errorf("Incorrect type used for randao mixes") - } + return convertRandaoMixes(indices, elements, convertAll) case types.Eth1DataVotes: - val, ok := elements.([]*ethpb.Eth1Data) - if !ok { - return nil, errors.Errorf("Wanted type of %v but got %v", - reflect.TypeOf([]*ethpb.Eth1Data{}).Name(), reflect.TypeOf(elements).Name()) - } - return handleEth1DataSlice(val, indices, convertAll) + return convertEth1DataVotes(indices, elements, convertAll) case types.Validators: - val, ok := elements.([]*ethpb.Validator) - if !ok { - return nil, errors.Errorf("Wanted type of %v but got %v", - reflect.TypeOf([]*ethpb.Validator{}).Name(), reflect.TypeOf(elements).Name()) - } - return handleValidatorSlice(val, indices, convertAll) + return convertValidators(indices, elements, convertAll) case types.PreviousEpochAttestations, types.CurrentEpochAttestations: - val, ok := elements.([]*ethpb.PendingAttestation) - if !ok { - return nil, errors.Errorf("Wanted type of %v but got %v", - reflect.TypeOf([]*ethpb.PendingAttestation{}).Name(), reflect.TypeOf(elements).Name()) - } - return handlePendingAttestationSlice(val, indices, convertAll) + return convertAttestations(indices, elements, convertAll) case types.Balances: - val, ok := elements.([]uint64) - if !ok { - return nil, errors.Errorf("Wanted type of %v but got %v", - reflect.TypeOf([]uint64{}).Name(), reflect.TypeOf(elements).Name()) - } - return handleBalanceSlice(val, indices, convertAll) + return convertBalances(indices, elements, convertAll) default: return [][32]byte{}, errors.Errorf("got unsupported type of %v", reflect.TypeOf(elements).Name()) } } +// fieldConvertersNative converts the corresponding field and the provided elements to the appropriate roots. +func fieldConvertersNative(field types.BeaconStateField, indices []uint64, elements interface{}, convertAll bool) ([][32]byte, error) { + switch field { + case nativetypes.BlockRoots: + return convertBlockRoots(indices, elements, convertAll) + case nativetypes.StateRoots: + return convertStateRoots(indices, elements, convertAll) + case nativetypes.RandaoMixes: + return convertRandaoMixes(indices, elements, convertAll) + case nativetypes.Eth1DataVotes: + return convertEth1DataVotes(indices, elements, convertAll) + case nativetypes.Validators: + return convertValidators(indices, elements, convertAll) + case nativetypes.PreviousEpochAttestations, nativetypes.CurrentEpochAttestations: + return convertAttestations(indices, elements, convertAll) + case nativetypes.Balances: + return convertBalances(indices, elements, convertAll) + default: + return [][32]byte{}, errors.Errorf("got unsupported type of %v", reflect.TypeOf(elements).Name()) + } +} + +func convertBlockRoots(indices []uint64, elements interface{}, convertAll bool) ([][32]byte, error) { + switch val := elements.(type) { + case [][]byte: + return handleByteArrays(val, indices, convertAll) + case *customtypes.BlockRoots: + return handle32ByteArrays(val[:], indices, convertAll) + default: + return nil, errors.Errorf("Incorrect type used for block roots") + } +} + +func convertStateRoots(indices []uint64, elements interface{}, convertAll bool) ([][32]byte, error) { + switch val := elements.(type) { + case [][]byte: + return handleByteArrays(val, indices, convertAll) + case *customtypes.StateRoots: + return handle32ByteArrays(val[:], indices, convertAll) + default: + return nil, errors.Errorf("Incorrect type used for state roots") + } +} + +func convertRandaoMixes(indices []uint64, elements interface{}, convertAll bool) ([][32]byte, error) { + switch val := elements.(type) { + case [][]byte: + return handleByteArrays(val, indices, convertAll) + case *customtypes.RandaoMixes: + return handle32ByteArrays(val[:], indices, convertAll) + default: + return nil, errors.Errorf("Incorrect type used for randao mixes") + } +} + +func convertEth1DataVotes(indices []uint64, elements interface{}, convertAll bool) ([][32]byte, error) { + val, ok := elements.([]*ethpb.Eth1Data) + if !ok { + return nil, errors.Errorf("Wanted type of %v but got %v", + reflect.TypeOf([]*ethpb.Eth1Data{}).Name(), reflect.TypeOf(elements).Name()) + } + return handleEth1DataSlice(val, indices, convertAll) +} + +func convertValidators(indices []uint64, elements interface{}, convertAll bool) ([][32]byte, error) { + val, ok := elements.([]*ethpb.Validator) + if !ok { + return nil, errors.Errorf("Wanted type of %v but got %v", + reflect.TypeOf([]*ethpb.Validator{}).Name(), reflect.TypeOf(elements).Name()) + } + return handleValidatorSlice(val, indices, convertAll) +} + +func convertAttestations(indices []uint64, elements interface{}, convertAll bool) ([][32]byte, error) { + val, ok := elements.([]*ethpb.PendingAttestation) + if !ok { + return nil, errors.Errorf("Wanted type of %v but got %v", + reflect.TypeOf([]*ethpb.PendingAttestation{}).Name(), reflect.TypeOf(elements).Name()) + } + return handlePendingAttestationSlice(val, indices, convertAll) +} + +func convertBalances(indices []uint64, elements interface{}, convertAll bool) ([][32]byte, error) { + val, ok := elements.([]uint64) + if !ok { + return nil, errors.Errorf("Wanted type of %v but got %v", + reflect.TypeOf([]uint64{}).Name(), reflect.TypeOf(elements).Name()) + } + return handleBalanceSlice(val, indices, convertAll) +} + // handleByteArrays computes and returns byte arrays in a slice of root format. func handleByteArrays(val [][]byte, indices []uint64, convertAll bool) ([][32]byte, error) { length := len(indices) diff --git a/beacon-chain/state/fieldtrie/field_trie_test.go b/beacon-chain/state/fieldtrie/field_trie_test.go index 813df0d880..193db6185c 100644 --- a/beacon-chain/state/fieldtrie/field_trie_test.go +++ b/beacon-chain/state/fieldtrie/field_trie_test.go @@ -18,7 +18,7 @@ func TestFieldTrie_NewTrie(t *testing.T) { newState, _ := util.DeterministicGenesisState(t, 40) // 5 represents the enum value of state roots - trie, err := fieldtrie.NewFieldTrie(5, stateTypes.BasicArray, newState.StateRoots(), uint64(params.BeaconConfig().SlotsPerHistoricalRoot)) + trie, err := fieldtrie.NewFieldTrie(stateTypes.FieldIndex(5), stateTypes.BasicArray, newState.StateRoots(), uint64(params.BeaconConfig().SlotsPerHistoricalRoot)) require.NoError(t, err) root, err := stateutil.RootsArrayHashTreeRoot(newState.StateRoots(), uint64(params.BeaconConfig().SlotsPerHistoricalRoot)) require.NoError(t, err) @@ -30,7 +30,7 @@ func TestFieldTrie_NewTrie(t *testing.T) { func TestFieldTrie_RecomputeTrie(t *testing.T) { newState, _ := util.DeterministicGenesisState(t, 32) // 10 represents the enum value of validators - trie, err := fieldtrie.NewFieldTrie(11, stateTypes.CompositeArray, newState.Validators(), params.BeaconConfig().ValidatorRegistryLimit) + trie, err := fieldtrie.NewFieldTrie(stateTypes.FieldIndex(11), stateTypes.CompositeArray, newState.Validators(), params.BeaconConfig().ValidatorRegistryLimit) require.NoError(t, err) changedIdx := []uint64{2, 29} @@ -58,7 +58,7 @@ func TestFieldTrie_RecomputeTrie(t *testing.T) { func TestFieldTrie_CopyTrieImmutable(t *testing.T) { newState, _ := util.DeterministicGenesisState(t, 32) // 12 represents the enum value of randao mixes. - trie, err := fieldtrie.NewFieldTrie(13, stateTypes.BasicArray, newState.RandaoMixes(), uint64(params.BeaconConfig().EpochsPerHistoricalVector)) + trie, err := fieldtrie.NewFieldTrie(stateTypes.FieldIndex(13), stateTypes.BasicArray, newState.RandaoMixes(), uint64(params.BeaconConfig().EpochsPerHistoricalVector)) require.NoError(t, err) newTrie := trie.CopyTrie() diff --git a/beacon-chain/state/state-native/v1/BUILD.bazel b/beacon-chain/state/state-native/BUILD.bazel similarity index 80% rename from beacon-chain/state/state-native/v1/BUILD.bazel rename to beacon-chain/state/state-native/BUILD.bazel index d23a79aa7b..70508e05af 100644 --- a/beacon-chain/state/state-native/v1/BUILD.bazel +++ b/beacon-chain/state/state-native/BUILD.bazel @@ -1,20 +1,21 @@ load("@prysm//tools/go:def.bzl", "go_library", "go_test") -load("//proto:ssz_proto_library.bzl", "ssz_proto_files") -load("//tools:ssz.bzl", "SSZ_DEPS", "ssz_gen_marshal") go_library( name = "go_default_library", srcs = [ "doc.go", - "field_roots.go", "getters_attestation.go", "getters_block.go", "getters_checkpoint.go", "getters_eth1.go", "getters_misc.go", + "getters_participation.go", + "getters_payload_header.go", "getters_randao.go", "getters_state.go", + "getters_sync_committee.go", "getters_validator.go", + "hasher.go", "proofs.go", "readonly_validator.go", "setters_attestation.go", @@ -22,19 +23,20 @@ go_library( "setters_checkpoint.go", "setters_eth1.go", "setters_misc.go", + "setters_participation.go", + "setters_payload_header.go", "setters_randao.go", "setters_state.go", + "setters_sync_committee.go", "setters_validator.go", + "ssz.go", "state_trie.go", "types.go", - "unsupported_getters.go", - "unsupported_setters.go", - ":ssz_generated_files", # keep ] + select({ "//config:mainnet": ["beacon_state_mainnet.go"], "//config:minimal": ["beacon_state_minimal.go"], }), - importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/v1", + importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native", visibility = [ "//beacon-chain:__subpackages__", "//contracts/deposit:__subpackages__", @@ -54,6 +56,7 @@ go_library( "//beacon-chain/state:go_default_library", "//beacon-chain/state/fieldtrie:go_default_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", "//beacon-chain/state/types:go_default_library", "//config/fieldparams:go_default_library", @@ -65,7 +68,6 @@ go_library( "//encoding/ssz:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//runtime/version:go_default_library", - "@com_github_ferranbt_fastssz//:go_default_library", "@com_github_pkg_errors//:go_default_library", "@com_github_prysmaticlabs_go_bitfield//:go_default_library", "@io_opencensus_go//trace:go_default_library", @@ -73,14 +75,15 @@ go_library( ], ) -# gazelle:exclude types_bench_test.go go_test( name = "go_default_test", srcs = [ "getters_attestation_test.go", "getters_block_test.go", + "getters_checkpoint_test.go", "getters_test.go", "getters_validator_test.go", + "hasher_test.go", "proofs_test.go", "readonly_validator_test.go", "references_test.go", @@ -95,9 +98,12 @@ go_test( embed = [":go_default_library"], deps = [ "//beacon-chain/state:go_default_library", + "//beacon-chain/state/state-native/types:go_default_library", "//beacon-chain/state/stateutil:go_default_library", "//beacon-chain/state/testing:go_default_library", - "//beacon-chain/state/types:go_default_library", + "//beacon-chain/state/v1:go_default_library", + "//beacon-chain/state/v2:go_default_library", + "//beacon-chain/state/v3:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", "//consensus-types/primitives:go_default_library", @@ -113,20 +119,3 @@ go_test( "@org_golang_google_protobuf//proto:go_default_library", ], ) - -ssz_gen_marshal( - name = "ssz_generated_files", - srcs = select({ - "//config:mainnet": ["beacon_state_mainnet.go"], - "//config:minimal": ["beacon_state_minimal.go"], - }), - includes = [ - "//beacon-chain/state/state-native/custom-types:go_default_library", - "//config/fieldparams:go_default_library", - "//consensus-types/primitives:go_default_library", - "//proto/prysm/v1alpha1:go_default_library", - ], - objs = [ - "BeaconState[no-htr]", - ], -) diff --git a/beacon-chain/state/state-native/v3/beacon_state_mainnet.go b/beacon-chain/state/state-native/beacon_state_mainnet.go similarity index 79% rename from beacon-chain/state/state-native/v3/beacon_state_mainnet.go rename to beacon-chain/state/state-native/beacon_state_mainnet.go index 1b247e5dc9..f3f5d5c9d4 100644 --- a/beacon-chain/state/state-native/v3/beacon_state_mainnet.go +++ b/beacon-chain/state/state-native/beacon_state_mainnet.go @@ -1,7 +1,7 @@ //go:build !minimal // +build !minimal -package v3 +package state_native import ( "sync" @@ -9,15 +9,16 @@ import ( "github.com/prysmaticlabs/go-bitfield" "github.com/prysmaticlabs/prysm/beacon-chain/state/fieldtrie" customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types" + nativetypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/types" "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - "github.com/prysmaticlabs/prysm/beacon-chain/state/types" eth2types "github.com/prysmaticlabs/prysm/consensus-types/primitives" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ) -// BeaconState defines a struct containing utilities for the eth2 chain state, defining +// BeaconState defines a struct containing utilities for the Ethereum Beacon Chain state, defining // getters and setters for its respective values and helpful functions such as HashTreeRoot(). type BeaconState struct { + version int genesisTime uint64 `ssz-gen:"true"` genesisValidatorsRoot customtypes.Byte32 `ssz-gen:"true" ssz-size:"32"` slot eth2types.Slot `ssz-gen:"true"` @@ -33,6 +34,8 @@ type BeaconState struct { balances []uint64 `ssz-gen:"true" ssz-max:"1099511627776"` randaoMixes *customtypes.RandaoMixes `ssz-gen:"true" ssz-size:"65536,32"` slashings []uint64 `ssz-gen:"true" ssz-size:"8192"` + previousEpochAttestations []*ethpb.PendingAttestation `ssz-gen:"true" ssz-max:"4096"` + currentEpochAttestations []*ethpb.PendingAttestation `ssz-gen:"true" ssz-max:"4096"` previousEpochParticipation []byte `ssz-gen:"true" ssz-max:"1099511627776"` currentEpochParticipation []byte `ssz-gen:"true" ssz-max:"1099511627776"` justificationBits bitfield.Bitvector4 `ssz-gen:"true" ssz-size:"1"` @@ -45,11 +48,11 @@ type BeaconState struct { latestExecutionPayloadHeader *ethpb.ExecutionPayloadHeader `ssz-gen:"true"` lock sync.RWMutex - dirtyFields map[types.FieldIndex]bool - dirtyIndices map[types.FieldIndex][]uint64 - stateFieldLeaves map[types.FieldIndex]*fieldtrie.FieldTrie - rebuildTrie map[types.FieldIndex]bool + dirtyFields map[nativetypes.FieldIndex]bool + dirtyIndices map[nativetypes.FieldIndex][]uint64 + stateFieldLeaves map[nativetypes.FieldIndex]*fieldtrie.FieldTrie + rebuildTrie map[nativetypes.FieldIndex]bool valMapHandler *stateutil.ValidatorMapHandler merkleLayers [][][]byte - sharedFieldReferences map[types.FieldIndex]*stateutil.Reference + sharedFieldReferences map[nativetypes.FieldIndex]*stateutil.Reference } diff --git a/beacon-chain/state/state-native/v1/beacon_state_mainnet_test.go b/beacon-chain/state/state-native/beacon_state_mainnet_test.go similarity index 93% rename from beacon-chain/state/state-native/v1/beacon_state_mainnet_test.go rename to beacon-chain/state/state-native/beacon_state_mainnet_test.go index 3644a61820..99cd602123 100644 --- a/beacon-chain/state/state-native/v1/beacon_state_mainnet_test.go +++ b/beacon-chain/state/state-native/beacon_state_mainnet_test.go @@ -1,7 +1,7 @@ //go:build !minimal // +build !minimal -package v1 +package state_native import ( "reflect" @@ -9,6 +9,7 @@ import ( "testing" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" + "github.com/prysmaticlabs/prysm/testing/assert" "github.com/prysmaticlabs/prysm/testing/require" ) @@ -79,4 +80,9 @@ func TestMainnetSszValuesAgainstFieldParams(t *testing.T) { require.Equal(t, true, ok, "Required field not found") v = f.Tag.Get("ssz-size") assert.Equal(t, "1", v) + + f, ok = bsType.FieldByName("inactivityScores") + require.Equal(t, true, ok, "Required field not found") + v = f.Tag.Get("ssz-max") + assert.Equal(t, strconv.Itoa(fieldparams.ValidatorRegistryLimit), v) } diff --git a/beacon-chain/state/state-native/v3/beacon_state_minimal.go b/beacon-chain/state/state-native/beacon_state_minimal.go similarity index 79% rename from beacon-chain/state/state-native/v3/beacon_state_minimal.go rename to beacon-chain/state/state-native/beacon_state_minimal.go index 8e7a8ac59e..cf893ffae9 100644 --- a/beacon-chain/state/state-native/v3/beacon_state_minimal.go +++ b/beacon-chain/state/state-native/beacon_state_minimal.go @@ -1,7 +1,7 @@ //go:build minimal // +build minimal -package v3 +package state_native import ( "sync" @@ -9,15 +9,16 @@ import ( "github.com/prysmaticlabs/go-bitfield" "github.com/prysmaticlabs/prysm/beacon-chain/state/fieldtrie" customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types" + nativetypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/types" "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - "github.com/prysmaticlabs/prysm/beacon-chain/state/types" eth2types "github.com/prysmaticlabs/prysm/consensus-types/primitives" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ) -// BeaconState defines a struct containing utilities for the eth2 chain state, defining +// BeaconState defines a struct containing utilities for the Ethereum Beacon Chain state, defining // getters and setters for its respective values and helpful functions such as HashTreeRoot(). type BeaconState struct { + version int genesisTime uint64 `ssz-gen:"true"` genesisValidatorsRoot customtypes.Byte32 `ssz-gen:"true" ssz-size:"32"` slot eth2types.Slot `ssz-gen:"true"` @@ -33,6 +34,8 @@ type BeaconState struct { balances []uint64 `ssz-gen:"true" ssz-max:"1099511627776"` randaoMixes *customtypes.RandaoMixes `ssz-gen:"true" ssz-size:"64,32"` slashings []uint64 `ssz-gen:"true" ssz-size:"64"` + previousEpochAttestations []*ethpb.PendingAttestation `ssz-gen:"true" ssz-max:"1024"` + currentEpochAttestations []*ethpb.PendingAttestation `ssz-gen:"true" ssz-max:"1024"` previousEpochParticipation []byte `ssz-gen:"true" ssz-max:"1099511627776"` currentEpochParticipation []byte `ssz-gen:"true" ssz-max:"1099511627776"` justificationBits bitfield.Bitvector4 `ssz-gen:"true" ssz-size:"1"` @@ -45,11 +48,11 @@ type BeaconState struct { latestExecutionPayloadHeader *ethpb.ExecutionPayloadHeader `ssz-gen:"true"` lock sync.RWMutex - dirtyFields map[types.FieldIndex]bool - dirtyIndices map[types.FieldIndex][]uint64 - stateFieldLeaves map[types.FieldIndex]*fieldtrie.FieldTrie - rebuildTrie map[types.FieldIndex]bool + dirtyFields map[nativetypes.FieldIndex]bool + dirtyIndices map[nativetypes.FieldIndex][]uint64 + stateFieldLeaves map[nativetypes.FieldIndex]*fieldtrie.FieldTrie + rebuildTrie map[nativetypes.FieldIndex]bool valMapHandler *stateutil.ValidatorMapHandler merkleLayers [][][]byte - sharedFieldReferences map[types.FieldIndex]*stateutil.Reference + sharedFieldReferences map[nativetypes.FieldIndex]*stateutil.Reference } diff --git a/beacon-chain/state/state-native/v1/beacon_state_minimal_test.go b/beacon-chain/state/state-native/beacon_state_minimal_test.go similarity index 93% rename from beacon-chain/state/state-native/v1/beacon_state_minimal_test.go rename to beacon-chain/state/state-native/beacon_state_minimal_test.go index 76dd691da0..17f2fa3698 100644 --- a/beacon-chain/state/state-native/v1/beacon_state_minimal_test.go +++ b/beacon-chain/state/state-native/beacon_state_minimal_test.go @@ -1,7 +1,7 @@ //go:build minimal // +build minimal -package v1 +package state_native import ( "reflect" @@ -79,4 +79,9 @@ func TestMinimalSszValuesAgainstFieldParams(t *testing.T) { require.Equal(t, true, ok, "Required field not found") v = f.Tag.Get("ssz-size") assert.Equal(t, "1", v) + + f, ok = bsType.FieldByName("inactivityScores") + require.Equal(t, true, ok, "Required field not found") + v = f.Tag.Get("ssz-max") + assert.Equal(t, strconv.Itoa(fieldparams.ValidatorRegistryLimit), v) } diff --git a/beacon-chain/state/state-native/v1/doc.go b/beacon-chain/state/state-native/doc.go similarity index 51% rename from beacon-chain/state/state-native/v1/doc.go rename to beacon-chain/state/state-native/doc.go index d47c3fb247..53459e6107 100644 --- a/beacon-chain/state/state-native/v1/doc.go +++ b/beacon-chain/state/state-native/doc.go @@ -1,22 +1,15 @@ -// Package v1 defines how the beacon chain state for Ethereum +// Package state_native defines how the beacon chain state for Ethereum // functions in the running beacon node, using an advanced, // immutable implementation of the state data structure. // // BeaconState getters may be accessed from inside or outside the package. To // avoid duplicating locks, we have internal and external versions of the -// getter The external function carries out the short-circuit conditions, -// obtains a read lock, then calls the internal function. The internal function -// carries out the short-circuit conditions and returns the required data -// without further locking, allowing it to be used by other package-level -// functions that already hold a lock. Hence the functions look something -// like this: +// getter. The external function obtains a read lock, then calls the internal function. +// The internal function returns the required data without further locking, +// allowing it to be used by other package-level functions that already hold a lock. +// Hence the functions look something like this: // // func (b *BeaconState) Foo() uint64 { -// // Short-circuit conditions. -// if !b.hasInnerState() { -// return 0 -// } -// // // Read lock. // b.lock.RLock() // defer b.lock.RUnlock() @@ -26,15 +19,12 @@ // } // // func (b *BeaconState) foo() uint64 { -// // Short-circuit conditions. -// if !b.hasInnerState() { -// return 0 -// } +// (...) // Some processing logic. // -// return b.state.foo +// return b.foo // } // // Although it is technically possible to remove the short-circuit conditions // from the external function, that would require every read to obtain a lock // even if the data was not present, leading to potential slowdowns. -package v1 +package state_native diff --git a/beacon-chain/state/state-native/v1/getters_attestation.go b/beacon-chain/state/state-native/getters_attestation.go similarity index 81% rename from beacon-chain/state/state-native/v1/getters_attestation.go rename to beacon-chain/state/state-native/getters_attestation.go index a76ad5accb..4ffc596b38 100644 --- a/beacon-chain/state/state-native/v1/getters_attestation.go +++ b/beacon-chain/state/state-native/getters_attestation.go @@ -1,11 +1,16 @@ -package v1 +package state_native import ( ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/runtime/version" ) // PreviousEpochAttestations corresponding to blocks on the beacon chain. func (b *BeaconState) PreviousEpochAttestations() ([]*ethpb.PendingAttestation, error) { + if b.version != version.Phase0 { + return nil, errNotSupported("PreviousEpochAttestations", b.version) + } + if b.previousEpochAttestations == nil { return nil, nil } @@ -24,6 +29,10 @@ func (b *BeaconState) previousEpochAttestationsVal() []*ethpb.PendingAttestation // CurrentEpochAttestations corresponding to blocks on the beacon chain. func (b *BeaconState) CurrentEpochAttestations() ([]*ethpb.PendingAttestation, error) { + if b.version != version.Phase0 { + return nil, errNotSupported("CurrentEpochAttestations", b.version) + } + if b.currentEpochAttestations == nil { return nil, nil } diff --git a/beacon-chain/state/state-native/v1/getters_attestation_test.go b/beacon-chain/state/state-native/getters_attestation_test.go similarity index 78% rename from beacon-chain/state/state-native/v1/getters_attestation_test.go rename to beacon-chain/state/state-native/getters_attestation_test.go index af85b2661a..7b490ca410 100644 --- a/beacon-chain/state/state-native/v1/getters_attestation_test.go +++ b/beacon-chain/state/state-native/getters_attestation_test.go @@ -1,4 +1,4 @@ -package v1 +package state_native import ( "testing" @@ -8,14 +8,14 @@ import ( ) func TestBeaconState_PreviousEpochAttestations(t *testing.T) { - s, err := InitializeFromProto(ðpb.BeaconState{}) + s, err := InitializeFromProtoPhase0(ðpb.BeaconState{}) require.NoError(t, err) atts, err := s.PreviousEpochAttestations() require.NoError(t, err) require.DeepEqual(t, []*ethpb.PendingAttestation(nil), atts) want := []*ethpb.PendingAttestation{{ProposerIndex: 100}} - s, err = InitializeFromProto(ðpb.BeaconState{PreviousEpochAttestations: want}) + s, err = InitializeFromProtoPhase0(ðpb.BeaconState{PreviousEpochAttestations: want}) require.NoError(t, err) got, err := s.PreviousEpochAttestations() require.NoError(t, err) @@ -27,14 +27,14 @@ func TestBeaconState_PreviousEpochAttestations(t *testing.T) { } func TestBeaconState_CurrentEpochAttestations(t *testing.T) { - s, err := InitializeFromProto(ðpb.BeaconState{}) + s, err := InitializeFromProtoPhase0(ðpb.BeaconState{}) require.NoError(t, err) atts, err := s.CurrentEpochAttestations() require.NoError(t, err) require.DeepEqual(t, []*ethpb.PendingAttestation(nil), atts) want := []*ethpb.PendingAttestation{{ProposerIndex: 101}} - s, err = InitializeFromProto(ðpb.BeaconState{CurrentEpochAttestations: want}) + s, err = InitializeFromProtoPhase0(ðpb.BeaconState{CurrentEpochAttestations: want}) require.NoError(t, err) got, err := s.CurrentEpochAttestations() require.NoError(t, err) diff --git a/beacon-chain/state/state-native/v1/getters_block.go b/beacon-chain/state/state-native/getters_block.go similarity index 98% rename from beacon-chain/state/state-native/v1/getters_block.go rename to beacon-chain/state/state-native/getters_block.go index 0fd7ce3575..bde96ee552 100644 --- a/beacon-chain/state/state-native/v1/getters_block.go +++ b/beacon-chain/state/state-native/getters_block.go @@ -1,4 +1,4 @@ -package v1 +package state_native import ( "fmt" diff --git a/beacon-chain/state/state-native/getters_block_test.go b/beacon-chain/state/state-native/getters_block_test.go new file mode 100644 index 0000000000..e6e4303217 --- /dev/null +++ b/beacon-chain/state/state-native/getters_block_test.go @@ -0,0 +1,117 @@ +package state_native + +import ( + "testing" + + "github.com/prysmaticlabs/prysm/beacon-chain/state" + testtmpl "github.com/prysmaticlabs/prysm/beacon-chain/state/testing" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +func TestBeaconState_LatestBlockHeader_Phase0(t *testing.T) { + testtmpl.VerifyBeaconStateLatestBlockHeader( + t, + func() (state.BeaconState, error) { + return InitializeFromProtoPhase0(ðpb.BeaconState{}) + }, + func(BH *ethpb.BeaconBlockHeader) (state.BeaconState, error) { + return InitializeFromProtoPhase0(ðpb.BeaconState{LatestBlockHeader: BH}) + }, + ) +} + +func TestBeaconState_LatestBlockHeader_Altair(t *testing.T) { + testtmpl.VerifyBeaconStateLatestBlockHeader( + t, + func() (state.BeaconState, error) { + return InitializeFromProtoAltair(ðpb.BeaconStateAltair{}) + }, + func(BH *ethpb.BeaconBlockHeader) (state.BeaconState, error) { + return InitializeFromProtoAltair(ðpb.BeaconStateAltair{LatestBlockHeader: BH}) + }, + ) +} + +func TestBeaconState_LatestBlockHeader_Bellatrix(t *testing.T) { + testtmpl.VerifyBeaconStateLatestBlockHeader( + t, + func() (state.BeaconState, error) { + return InitializeFromProtoBellatrix(ðpb.BeaconStateBellatrix{}) + }, + func(BH *ethpb.BeaconBlockHeader) (state.BeaconState, error) { + return InitializeFromProtoBellatrix(ðpb.BeaconStateBellatrix{LatestBlockHeader: BH}) + }, + ) +} + +func TestBeaconState_BlockRoots_Phase0(t *testing.T) { + testtmpl.VerifyBeaconStateBlockRootsNative( + t, + func() (state.BeaconState, error) { + return InitializeFromProtoPhase0(ðpb.BeaconState{}) + }, + func(BR [][]byte) (state.BeaconState, error) { + return InitializeFromProtoPhase0(ðpb.BeaconState{BlockRoots: BR}) + }, + ) +} + +func TestBeaconState_BlockRoots_Altair(t *testing.T) { + testtmpl.VerifyBeaconStateBlockRootsNative( + t, + func() (state.BeaconState, error) { + return InitializeFromProtoAltair(ðpb.BeaconStateAltair{}) + }, + func(BR [][]byte) (state.BeaconState, error) { + return InitializeFromProtoAltair(ðpb.BeaconStateAltair{BlockRoots: BR}) + }, + ) +} + +func TestBeaconState_BlockRoots_Bellatrix(t *testing.T) { + testtmpl.VerifyBeaconStateBlockRootsNative( + t, + func() (state.BeaconState, error) { + return InitializeFromProtoBellatrix(ðpb.BeaconStateBellatrix{}) + }, + func(BR [][]byte) (state.BeaconState, error) { + return InitializeFromProtoBellatrix(ðpb.BeaconStateBellatrix{BlockRoots: BR}) + }, + ) +} + +func TestBeaconState_BlockRootAtIndex_Phase0(t *testing.T) { + testtmpl.VerifyBeaconStateBlockRootAtIndexNative( + t, + func() (state.BeaconState, error) { + return InitializeFromProtoPhase0(ðpb.BeaconState{}) + }, + func(BR [][]byte) (state.BeaconState, error) { + return InitializeFromProtoPhase0(ðpb.BeaconState{BlockRoots: BR}) + }, + ) +} + +func TestBeaconState_BlockRootAtIndex_Altair(t *testing.T) { + testtmpl.VerifyBeaconStateBlockRootAtIndexNative( + t, + func() (state.BeaconState, error) { + return InitializeFromProtoAltair(ðpb.BeaconStateAltair{}) + }, + func(BR [][]byte) (state.BeaconState, error) { + return InitializeFromProtoAltair(ðpb.BeaconStateAltair{BlockRoots: BR}) + }, + ) +} + +func TestBeaconState_BlockRootAtIndex_Bellatrix(t *testing.T) { + testtmpl.VerifyBeaconStateBlockRootAtIndexNative( + t, + func() (state.BeaconState, error) { + return InitializeFromProtoBellatrix(ðpb.BeaconStateBellatrix{}) + }, + func(BR [][]byte) (state.BeaconState, error) { + return InitializeFromProtoBellatrix(ðpb.BeaconStateBellatrix{BlockRoots: BR}) + }, + ) +} diff --git a/beacon-chain/state/state-native/v3/getters_checkpoint.go b/beacon-chain/state/state-native/getters_checkpoint.go similarity index 99% rename from beacon-chain/state/state-native/v3/getters_checkpoint.go rename to beacon-chain/state/state-native/getters_checkpoint.go index dac45b034e..117304ded7 100644 --- a/beacon-chain/state/state-native/v3/getters_checkpoint.go +++ b/beacon-chain/state/state-native/getters_checkpoint.go @@ -1,4 +1,4 @@ -package v3 +package state_native import ( "bytes" diff --git a/beacon-chain/state/state-native/getters_checkpoint_test.go b/beacon-chain/state/state-native/getters_checkpoint_test.go new file mode 100644 index 0000000000..f0131b81d7 --- /dev/null +++ b/beacon-chain/state/state-native/getters_checkpoint_test.go @@ -0,0 +1,202 @@ +package state_native + +import ( + "testing" + + "github.com/prysmaticlabs/go-bitfield" + "github.com/prysmaticlabs/prysm/beacon-chain/state" + testtmpl "github.com/prysmaticlabs/prysm/beacon-chain/state/testing" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +func TestBeaconState_PreviousJustifiedCheckpointNil_Phase0(t *testing.T) { + testtmpl.VerifyBeaconStatePreviousJustifiedCheckpointNil( + t, + func() (state.BeaconState, error) { + return InitializeFromProtoUnsafePhase0(ðpb.BeaconState{}) + }) +} + +func TestBeaconState_PreviousJustifiedCheckpointNil_Altair(t *testing.T) { + testtmpl.VerifyBeaconStatePreviousJustifiedCheckpointNil( + t, + func() (state.BeaconState, error) { + return InitializeFromProtoUnsafeAltair(ðpb.BeaconStateAltair{}) + }) +} + +func TestBeaconState_PreviousJustifiedCheckpointNil_Bellatrix(t *testing.T) { + testtmpl.VerifyBeaconStatePreviousJustifiedCheckpointNil( + t, + func() (state.BeaconState, error) { + return InitializeFromProtoUnsafeBellatrix(ðpb.BeaconStateBellatrix{}) + }) +} + +func TestBeaconState_PreviousJustifiedCheckpoint_Phase0(t *testing.T) { + testtmpl.VerifyBeaconStatePreviousJustifiedCheckpoint( + t, + func(cp *ethpb.Checkpoint) (state.BeaconState, error) { + return InitializeFromProtoUnsafePhase0(ðpb.BeaconState{PreviousJustifiedCheckpoint: cp}) + }) +} + +func TestBeaconState_PreviousJustifiedCheckpoint_Altair(t *testing.T) { + testtmpl.VerifyBeaconStatePreviousJustifiedCheckpoint( + t, + func(cp *ethpb.Checkpoint) (state.BeaconState, error) { + return InitializeFromProtoUnsafeAltair(ðpb.BeaconStateAltair{PreviousJustifiedCheckpoint: cp}) + }) +} + +func TestBeaconState_PreviousJustifiedCheckpoint_Bellatrix(t *testing.T) { + testtmpl.VerifyBeaconStatePreviousJustifiedCheckpoint( + t, + func(cp *ethpb.Checkpoint) (state.BeaconState, error) { + return InitializeFromProtoUnsafeBellatrix(ðpb.BeaconStateBellatrix{PreviousJustifiedCheckpoint: cp}) + }) +} + +func TestBeaconState_CurrentJustifiedCheckpointNil_Phase0(t *testing.T) { + testtmpl.VerifyBeaconStateCurrentJustifiedCheckpointNil( + t, + func() (state.BeaconState, error) { + return InitializeFromProtoUnsafePhase0(ðpb.BeaconState{}) + }) +} + +func TestBeaconState_CurrentJustifiedCheckpointNil_Altair(t *testing.T) { + testtmpl.VerifyBeaconStateCurrentJustifiedCheckpointNil( + t, + func() (state.BeaconState, error) { + return InitializeFromProtoUnsafeAltair(ðpb.BeaconStateAltair{}) + }) +} + +func TestBeaconState_CurrentJustifiedCheckpointNil_Bellatrix(t *testing.T) { + testtmpl.VerifyBeaconStateCurrentJustifiedCheckpointNil( + t, + func() (state.BeaconState, error) { + return InitializeFromProtoUnsafeBellatrix(ðpb.BeaconStateBellatrix{}) + }) +} + +func TestBeaconState_CurrentJustifiedCheckpoint_Phase0(t *testing.T) { + testtmpl.VerifyBeaconStateCurrentJustifiedCheckpoint( + t, + func(cp *ethpb.Checkpoint) (state.BeaconState, error) { + return InitializeFromProtoUnsafePhase0(ðpb.BeaconState{CurrentJustifiedCheckpoint: cp}) + }) +} + +func TestBeaconState_CurrentJustifiedCheckpoint_Altair(t *testing.T) { + testtmpl.VerifyBeaconStateCurrentJustifiedCheckpoint( + t, + func(cp *ethpb.Checkpoint) (state.BeaconState, error) { + return InitializeFromProtoUnsafeAltair(ðpb.BeaconStateAltair{CurrentJustifiedCheckpoint: cp}) + }) +} + +func TestBeaconState_CurrentJustifiedCheckpoint_Bellatrix(t *testing.T) { + testtmpl.VerifyBeaconStateCurrentJustifiedCheckpoint( + t, + func(cp *ethpb.Checkpoint) (state.BeaconState, error) { + return InitializeFromProtoUnsafeBellatrix(ðpb.BeaconStateBellatrix{CurrentJustifiedCheckpoint: cp}) + }) +} + +func TestBeaconState_FinalizedCheckpointNil_Phase0(t *testing.T) { + testtmpl.VerifyBeaconStateFinalizedCheckpointNil( + t, + func() (state.BeaconState, error) { + return InitializeFromProtoUnsafePhase0(ðpb.BeaconState{}) + }) +} + +func TestBeaconState_FinalizedCheckpointNil_Altair(t *testing.T) { + testtmpl.VerifyBeaconStateFinalizedCheckpointNil( + t, + func() (state.BeaconState, error) { + return InitializeFromProtoUnsafeAltair(ðpb.BeaconStateAltair{}) + }) +} + +func TestBeaconState_FinalizedCheckpointNil_Bellatrix(t *testing.T) { + testtmpl.VerifyBeaconStateFinalizedCheckpointNil( + t, + func() (state.BeaconState, error) { + return InitializeFromProtoUnsafeBellatrix(ðpb.BeaconStateBellatrix{}) + }) +} + +func TestBeaconState_FinalizedCheckpoint_Phase0(t *testing.T) { + testtmpl.VerifyBeaconStateFinalizedCheckpoint( + t, + func(cp *ethpb.Checkpoint) (state.BeaconState, error) { + return InitializeFromProtoUnsafePhase0(ðpb.BeaconState{FinalizedCheckpoint: cp}) + }) +} + +func TestBeaconState_FinalizedCheckpoint_Altair(t *testing.T) { + testtmpl.VerifyBeaconStateFinalizedCheckpoint( + t, + func(cp *ethpb.Checkpoint) (state.BeaconState, error) { + return InitializeFromProtoUnsafeAltair(ðpb.BeaconStateAltair{FinalizedCheckpoint: cp}) + }) +} + +func TestBeaconState_FinalizedCheckpoint_Bellatrix(t *testing.T) { + testtmpl.VerifyBeaconStateFinalizedCheckpoint( + t, + func(cp *ethpb.Checkpoint) (state.BeaconState, error) { + return InitializeFromProtoUnsafeBellatrix(ðpb.BeaconStateBellatrix{FinalizedCheckpoint: cp}) + }) +} + +func TestBeaconState_JustificationBitsNil_Phase0(t *testing.T) { + testtmpl.VerifyBeaconStateJustificationBitsNil( + t, + func() (state.BeaconState, error) { + return InitializeFromProtoUnsafePhase0(ðpb.BeaconState{}) + }) +} + +func TestBeaconState_JustificationBitsNil_Altair(t *testing.T) { + testtmpl.VerifyBeaconStateJustificationBitsNil( + t, + func() (state.BeaconState, error) { + return InitializeFromProtoUnsafeAltair(ðpb.BeaconStateAltair{}) + }) +} + +func TestBeaconState_JustificationBitsNil_Bellatrix(t *testing.T) { + testtmpl.VerifyBeaconStateJustificationBitsNil( + t, + func() (state.BeaconState, error) { + return InitializeFromProtoUnsafeBellatrix(ðpb.BeaconStateBellatrix{}) + }) +} + +func TestBeaconState_JustificationBits_Phase0(t *testing.T) { + testtmpl.VerifyBeaconStateJustificationBits( + t, + func(bits bitfield.Bitvector4) (state.BeaconState, error) { + return InitializeFromProtoUnsafePhase0(ðpb.BeaconState{JustificationBits: bits}) + }) +} + +func TestBeaconState_JustificationBits_Altair(t *testing.T) { + testtmpl.VerifyBeaconStateJustificationBits( + t, + func(bits bitfield.Bitvector4) (state.BeaconState, error) { + return InitializeFromProtoUnsafeAltair(ðpb.BeaconStateAltair{JustificationBits: bits}) + }) +} + +func TestBeaconState_JustificationBits_Bellatrix(t *testing.T) { + testtmpl.VerifyBeaconStateJustificationBits( + t, + func(bits bitfield.Bitvector4) (state.BeaconState, error) { + return InitializeFromProtoUnsafeBellatrix(ðpb.BeaconStateBellatrix{JustificationBits: bits}) + }) +} diff --git a/beacon-chain/state/state-native/v3/getters_eth1.go b/beacon-chain/state/state-native/getters_eth1.go similarity index 98% rename from beacon-chain/state/state-native/v3/getters_eth1.go rename to beacon-chain/state/state-native/getters_eth1.go index 55096f2933..35939ef27c 100644 --- a/beacon-chain/state/state-native/v3/getters_eth1.go +++ b/beacon-chain/state/state-native/getters_eth1.go @@ -1,4 +1,4 @@ -package v3 +package state_native import ( ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" diff --git a/beacon-chain/state/state-native/v2/getters_misc.go b/beacon-chain/state/state-native/getters_misc.go similarity index 93% rename from beacon-chain/state/state-native/v2/getters_misc.go rename to beacon-chain/state/state-native/getters_misc.go index 90719351e6..29aa8b5f58 100644 --- a/beacon-chain/state/state-native/v2/getters_misc.go +++ b/beacon-chain/state/state-native/getters_misc.go @@ -1,9 +1,8 @@ -package v2 +package state_native import ( types "github.com/prysmaticlabs/prysm/consensus-types/primitives" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/runtime/version" ) // GenesisTime of the beacon state as a uint64. @@ -25,8 +24,8 @@ func (b *BeaconState) GenesisValidatorsRoot() []byte { // Version of the beacon state. This method // is strictly meant to be used without a lock // internally. -func (_ *BeaconState) Version() int { - return version.Altair +func (b *BeaconState) Version() int { + return b.version } // Slot of the current beacon chain state. diff --git a/beacon-chain/state/state-native/v3/getters_participation.go b/beacon-chain/state/state-native/getters_participation.go similarity index 80% rename from beacon-chain/state/state-native/v3/getters_participation.go rename to beacon-chain/state/state-native/getters_participation.go index 10fb7073e4..c81a970285 100644 --- a/beacon-chain/state/state-native/v3/getters_participation.go +++ b/beacon-chain/state/state-native/getters_participation.go @@ -1,7 +1,15 @@ -package v3 +package state_native + +import ( + "github.com/prysmaticlabs/prysm/runtime/version" +) // CurrentEpochParticipation corresponding to participation bits on the beacon chain. func (b *BeaconState) CurrentEpochParticipation() ([]byte, error) { + if b.version == version.Phase0 { + return nil, errNotSupported("CurrentEpochParticipation", b.version) + } + if b.currentEpochParticipation == nil { return nil, nil } @@ -14,6 +22,10 @@ func (b *BeaconState) CurrentEpochParticipation() ([]byte, error) { // PreviousEpochParticipation corresponding to participation bits on the beacon chain. func (b *BeaconState) PreviousEpochParticipation() ([]byte, error) { + if b.version == version.Phase0 { + return nil, errNotSupported("PreviousEpochParticipation", b.version) + } + if b.previousEpochParticipation == nil { return nil, nil } diff --git a/beacon-chain/state/state-native/v3/getters_payload_header.go b/beacon-chain/state/state-native/getters_payload_header.go similarity index 75% rename from beacon-chain/state/state-native/v3/getters_payload_header.go rename to beacon-chain/state/state-native/getters_payload_header.go index 26251733e0..a62d68d2b6 100644 --- a/beacon-chain/state/state-native/v3/getters_payload_header.go +++ b/beacon-chain/state/state-native/getters_payload_header.go @@ -1,11 +1,16 @@ -package v3 +package state_native import ( ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/runtime/version" ) // LatestExecutionPayloadHeader of the beacon state. func (b *BeaconState) LatestExecutionPayloadHeader() (*ethpb.ExecutionPayloadHeader, error) { + if b.version == version.Phase0 || b.version == version.Altair { + return nil, errNotSupported("LatestExecutionPayloadHeader", b.version) + } + if b.latestExecutionPayloadHeader == nil { return nil, nil } diff --git a/beacon-chain/state/state-native/v3/getters_randao.go b/beacon-chain/state/state-native/getters_randao.go similarity index 98% rename from beacon-chain/state/state-native/v3/getters_randao.go rename to beacon-chain/state/state-native/getters_randao.go index 75f028e5cf..9f6de01de0 100644 --- a/beacon-chain/state/state-native/v3/getters_randao.go +++ b/beacon-chain/state/state-native/getters_randao.go @@ -1,4 +1,4 @@ -package v3 +package state_native import ( "fmt" diff --git a/beacon-chain/state/state-native/getters_state.go b/beacon-chain/state/state-native/getters_state.go new file mode 100644 index 0000000000..7816c17bac --- /dev/null +++ b/beacon-chain/state/state-native/getters_state.go @@ -0,0 +1,279 @@ +package state_native + +import ( + "fmt" + + "github.com/pkg/errors" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/runtime/version" +) + +// ToProtoUnsafe returns the pointer value of the underlying +// beacon state proto object, bypassing immutability. Use with care. +func (b *BeaconState) ToProtoUnsafe() interface{} { + if b == nil { + return nil + } + + gvrCopy := b.genesisValidatorsRoot + + switch b.version { + case version.Phase0: + return ðpb.BeaconState{ + GenesisTime: b.genesisTime, + GenesisValidatorsRoot: gvrCopy[:], + Slot: b.slot, + Fork: b.fork, + LatestBlockHeader: b.latestBlockHeader, + BlockRoots: b.blockRoots.Slice(), + StateRoots: b.stateRoots.Slice(), + HistoricalRoots: b.historicalRoots.Slice(), + Eth1Data: b.eth1Data, + Eth1DataVotes: b.eth1DataVotes, + Eth1DepositIndex: b.eth1DepositIndex, + Validators: b.validators, + Balances: b.balances, + RandaoMixes: b.randaoMixes.Slice(), + Slashings: b.slashings, + PreviousEpochAttestations: b.previousEpochAttestations, + CurrentEpochAttestations: b.currentEpochAttestations, + JustificationBits: b.justificationBits, + PreviousJustifiedCheckpoint: b.previousJustifiedCheckpoint, + CurrentJustifiedCheckpoint: b.currentJustifiedCheckpoint, + FinalizedCheckpoint: b.finalizedCheckpoint, + } + case version.Altair: + return ðpb.BeaconStateAltair{ + GenesisTime: b.genesisTime, + GenesisValidatorsRoot: gvrCopy[:], + Slot: b.slot, + Fork: b.fork, + LatestBlockHeader: b.latestBlockHeader, + BlockRoots: b.blockRoots.Slice(), + StateRoots: b.stateRoots.Slice(), + HistoricalRoots: b.historicalRoots.Slice(), + Eth1Data: b.eth1Data, + Eth1DataVotes: b.eth1DataVotes, + Eth1DepositIndex: b.eth1DepositIndex, + Validators: b.validators, + Balances: b.balances, + RandaoMixes: b.randaoMixes.Slice(), + Slashings: b.slashings, + PreviousEpochParticipation: b.previousEpochParticipation, + CurrentEpochParticipation: b.currentEpochParticipation, + JustificationBits: b.justificationBits, + PreviousJustifiedCheckpoint: b.previousJustifiedCheckpoint, + CurrentJustifiedCheckpoint: b.currentJustifiedCheckpoint, + FinalizedCheckpoint: b.finalizedCheckpoint, + InactivityScores: b.inactivityScores, + CurrentSyncCommittee: b.currentSyncCommittee, + NextSyncCommittee: b.nextSyncCommittee, + } + case version.Bellatrix: + return ðpb.BeaconStateBellatrix{ + GenesisTime: b.genesisTime, + GenesisValidatorsRoot: gvrCopy[:], + Slot: b.slot, + Fork: b.fork, + LatestBlockHeader: b.latestBlockHeader, + BlockRoots: b.blockRoots.Slice(), + StateRoots: b.stateRoots.Slice(), + HistoricalRoots: b.historicalRoots.Slice(), + Eth1Data: b.eth1Data, + Eth1DataVotes: b.eth1DataVotes, + Eth1DepositIndex: b.eth1DepositIndex, + Validators: b.validators, + Balances: b.balances, + RandaoMixes: b.randaoMixes.Slice(), + Slashings: b.slashings, + PreviousEpochParticipation: b.previousEpochParticipation, + CurrentEpochParticipation: b.currentEpochParticipation, + JustificationBits: b.justificationBits, + PreviousJustifiedCheckpoint: b.previousJustifiedCheckpoint, + CurrentJustifiedCheckpoint: b.currentJustifiedCheckpoint, + FinalizedCheckpoint: b.finalizedCheckpoint, + InactivityScores: b.inactivityScores, + CurrentSyncCommittee: b.currentSyncCommittee, + NextSyncCommittee: b.nextSyncCommittee, + LatestExecutionPayloadHeader: b.latestExecutionPayloadHeader, + } + default: + return nil + } +} + +// ToProto the beacon state into a protobuf for usage. +func (b *BeaconState) ToProto() interface{} { + if b == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + gvrCopy := b.genesisValidatorsRoot + + switch b.version { + case version.Phase0: + return ðpb.BeaconState{ + GenesisTime: b.genesisTime, + GenesisValidatorsRoot: gvrCopy[:], + Slot: b.slot, + Fork: b.forkVal(), + LatestBlockHeader: b.latestBlockHeaderVal(), + BlockRoots: b.blockRoots.Slice(), + StateRoots: b.stateRoots.Slice(), + HistoricalRoots: b.historicalRoots.Slice(), + Eth1Data: b.eth1DataVal(), + Eth1DataVotes: b.eth1DataVotesVal(), + Eth1DepositIndex: b.eth1DepositIndex, + Validators: b.validatorsVal(), + Balances: b.balancesVal(), + RandaoMixes: b.randaoMixes.Slice(), + Slashings: b.slashingsVal(), + PreviousEpochAttestations: b.previousEpochAttestationsVal(), + CurrentEpochAttestations: b.currentEpochAttestationsVal(), + JustificationBits: b.justificationBitsVal(), + PreviousJustifiedCheckpoint: b.previousJustifiedCheckpointVal(), + CurrentJustifiedCheckpoint: b.currentJustifiedCheckpointVal(), + FinalizedCheckpoint: b.finalizedCheckpointVal(), + } + case version.Altair: + return ðpb.BeaconStateAltair{ + GenesisTime: b.genesisTime, + GenesisValidatorsRoot: gvrCopy[:], + Slot: b.slot, + Fork: b.forkVal(), + LatestBlockHeader: b.latestBlockHeaderVal(), + BlockRoots: b.blockRoots.Slice(), + StateRoots: b.stateRoots.Slice(), + HistoricalRoots: b.historicalRoots.Slice(), + Eth1Data: b.eth1DataVal(), + Eth1DataVotes: b.eth1DataVotesVal(), + Eth1DepositIndex: b.eth1DepositIndex, + Validators: b.validatorsVal(), + Balances: b.balancesVal(), + RandaoMixes: b.randaoMixes.Slice(), + Slashings: b.slashingsVal(), + PreviousEpochParticipation: b.previousEpochParticipationVal(), + CurrentEpochParticipation: b.currentEpochParticipationVal(), + JustificationBits: b.justificationBitsVal(), + PreviousJustifiedCheckpoint: b.previousJustifiedCheckpointVal(), + CurrentJustifiedCheckpoint: b.currentJustifiedCheckpointVal(), + FinalizedCheckpoint: b.finalizedCheckpointVal(), + InactivityScores: b.inactivityScoresVal(), + CurrentSyncCommittee: b.currentSyncCommitteeVal(), + NextSyncCommittee: b.nextSyncCommitteeVal(), + } + case version.Bellatrix: + return ðpb.BeaconStateBellatrix{ + GenesisTime: b.genesisTime, + GenesisValidatorsRoot: gvrCopy[:], + Slot: b.slot, + Fork: b.forkVal(), + LatestBlockHeader: b.latestBlockHeaderVal(), + BlockRoots: b.blockRoots.Slice(), + StateRoots: b.stateRoots.Slice(), + HistoricalRoots: b.historicalRoots.Slice(), + Eth1Data: b.eth1DataVal(), + Eth1DataVotes: b.eth1DataVotesVal(), + Eth1DepositIndex: b.eth1DepositIndex, + Validators: b.validatorsVal(), + Balances: b.balancesVal(), + RandaoMixes: b.randaoMixes.Slice(), + Slashings: b.slashingsVal(), + PreviousEpochParticipation: b.previousEpochParticipationVal(), + CurrentEpochParticipation: b.currentEpochParticipationVal(), + JustificationBits: b.justificationBitsVal(), + PreviousJustifiedCheckpoint: b.previousJustifiedCheckpointVal(), + CurrentJustifiedCheckpoint: b.currentJustifiedCheckpointVal(), + FinalizedCheckpoint: b.finalizedCheckpointVal(), + InactivityScores: b.inactivityScoresVal(), + CurrentSyncCommittee: b.currentSyncCommitteeVal(), + NextSyncCommittee: b.nextSyncCommitteeVal(), + LatestExecutionPayloadHeader: b.latestExecutionPayloadHeaderVal(), + } + default: + return nil + } +} + +// StateRoots kept track of in the beacon state. +func (b *BeaconState) StateRoots() [][]byte { + if b.stateRoots == nil { + return nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.stateRoots.Slice() +} + +// StateRootAtIndex retrieves a specific state root based on an +// input index value. +func (b *BeaconState) StateRootAtIndex(idx uint64) ([]byte, error) { + if b.stateRoots == nil { + return nil, nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + r, err := b.stateRootAtIndex(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. +func (b *BeaconState) stateRootAtIndex(idx uint64) ([32]byte, error) { + if uint64(len(b.stateRoots)) <= idx { + return [32]byte{}, fmt.Errorf("index %d out of range", 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) { + pbState, ok := s.(*ethpb.BeaconState) + if !ok { + return nil, errors.New("input is not type ethpb.BeaconState") + } + return pbState, nil +} + +// ProtobufBeaconStateAltair transforms an input into beacon state Altair in the form of protobuf. +// Error is returned if the input is not type protobuf beacon state. +func ProtobufBeaconStateAltair(s interface{}) (*ethpb.BeaconStateAltair, error) { + pbState, ok := s.(*ethpb.BeaconStateAltair) + if !ok { + return nil, errors.New("input is not type pb.BeaconStateAltair") + } + return pbState, nil +} + +// ProtobufBeaconStateBellatrix transforms an input into beacon state Bellatrix in the form of protobuf. +// Error is returned if the input is not type protobuf beacon state. +func ProtobufBeaconStateBellatrix(s interface{}) (*ethpb.BeaconStateBellatrix, error) { + pbState, ok := s.(*ethpb.BeaconStateBellatrix) + if !ok { + return nil, errors.New("input is not type pb.BeaconStateBellatrix") + } + return pbState, nil +} + +// InnerStateUnsafe returns the pointer value of the underlying +// beacon state proto object, bypassing immutability. Use with care. +func (b *BeaconState) InnerStateUnsafe() interface{} { + return b.ToProtoUnsafe() +} + +// CloneInnerState the beacon state into a protobuf for usage. +func (b *BeaconState) CloneInnerState() interface{} { + return b.ToProto() +} diff --git a/beacon-chain/state/state-native/v2/getters_sync_committee.go b/beacon-chain/state/state-native/getters_sync_committee.go similarity index 72% rename from beacon-chain/state/state-native/v2/getters_sync_committee.go rename to beacon-chain/state/state-native/getters_sync_committee.go index b595b05f3d..4d6588670c 100644 --- a/beacon-chain/state/state-native/v2/getters_sync_committee.go +++ b/beacon-chain/state/state-native/getters_sync_committee.go @@ -1,27 +1,20 @@ -package v2 +package state_native import ( "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/runtime/version" ) -// currentSyncCommitteeVal of the current sync committee in beacon chain state. -// This assumes that a lock is already held on BeaconState. -func (b *BeaconState) currentSyncCommitteeVal() *ethpb.SyncCommittee { - return CopySyncCommittee(b.currentSyncCommittee) -} - -// nextSyncCommitteeVal of the next sync committee in beacon chain state. -// This assumes that a lock is already held on BeaconState. -func (b *BeaconState) nextSyncCommitteeVal() *ethpb.SyncCommittee { - return CopySyncCommittee(b.nextSyncCommittee) -} - // CurrentSyncCommittee of the current sync committee in beacon chain state. func (b *BeaconState) CurrentSyncCommittee() (*ethpb.SyncCommittee, error) { b.lock.RLock() defer b.lock.RUnlock() + if b.version == version.Phase0 { + return nil, errNotSupported("CurrentSyncCommittee", b.version) + } + if b.currentSyncCommittee == nil { return nil, nil } @@ -29,11 +22,21 @@ func (b *BeaconState) CurrentSyncCommittee() (*ethpb.SyncCommittee, error) { return b.currentSyncCommitteeVal(), nil } +// currentSyncCommitteeVal of the current sync committee in beacon chain state. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) currentSyncCommitteeVal() *ethpb.SyncCommittee { + return copySyncCommittee(b.currentSyncCommittee) +} + // NextSyncCommittee of the next sync committee in beacon chain state. func (b *BeaconState) NextSyncCommittee() (*ethpb.SyncCommittee, error) { b.lock.RLock() defer b.lock.RUnlock() + if b.version == version.Phase0 { + return nil, errNotSupported("NextSyncCommittee", b.version) + } + if b.nextSyncCommittee == nil { return nil, nil } @@ -41,8 +44,14 @@ func (b *BeaconState) NextSyncCommittee() (*ethpb.SyncCommittee, error) { return b.nextSyncCommitteeVal(), nil } -// CopySyncCommittee copies the provided sync committee object. -func CopySyncCommittee(data *ethpb.SyncCommittee) *ethpb.SyncCommittee { +// nextSyncCommitteeVal of the next sync committee in beacon chain state. +// This assumes that a lock is already held on BeaconState. +func (b *BeaconState) nextSyncCommitteeVal() *ethpb.SyncCommittee { + return copySyncCommittee(b.nextSyncCommittee) +} + +// copySyncCommittee copies the provided sync committee object. +func copySyncCommittee(data *ethpb.SyncCommittee) *ethpb.SyncCommittee { if data == nil { return nil } diff --git a/beacon-chain/state/state-native/getters_test.go b/beacon-chain/state/state-native/getters_test.go new file mode 100644 index 0000000000..13debf16f6 --- /dev/null +++ b/beacon-chain/state/state-native/getters_test.go @@ -0,0 +1,99 @@ +package state_native + +import ( + "testing" + + "github.com/prysmaticlabs/prysm/beacon-chain/state" + testtmpl "github.com/prysmaticlabs/prysm/beacon-chain/state/testing" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +func TestBeaconState_SlotDataRace_Phase0(t *testing.T) { + testtmpl.VerifyBeaconStateSlotDataRace(t, func() (state.BeaconState, error) { + return InitializeFromProtoPhase0(ðpb.BeaconState{Slot: 1}) + }) +} + +func TestBeaconState_SlotDataRace_Altair(t *testing.T) { + testtmpl.VerifyBeaconStateSlotDataRace(t, func() (state.BeaconState, error) { + return InitializeFromProtoAltair(ðpb.BeaconStateAltair{Slot: 1}) + }) +} + +func TestBeaconState_SlotDataRace_Bellatrix(t *testing.T) { + testtmpl.VerifyBeaconStateSlotDataRace(t, func() (state.BeaconState, error) { + return InitializeFromProtoBellatrix(ðpb.BeaconStateBellatrix{Slot: 1}) + }) +} + +func TestBeaconState_MatchCurrentJustifiedCheckpt_Phase0(t *testing.T) { + testtmpl.VerifyBeaconStateMatchCurrentJustifiedCheckptNative( + t, + func(cp *ethpb.Checkpoint) (state.BeaconState, error) { + return InitializeFromProtoPhase0(ðpb.BeaconState{CurrentJustifiedCheckpoint: cp}) + }, + ) +} + +func TestBeaconState_MatchCurrentJustifiedCheckpt_Altair(t *testing.T) { + testtmpl.VerifyBeaconStateMatchCurrentJustifiedCheckptNative( + t, + func(cp *ethpb.Checkpoint) (state.BeaconState, error) { + return InitializeFromProtoAltair(ðpb.BeaconStateAltair{CurrentJustifiedCheckpoint: cp}) + }, + ) +} + +func TestBeaconState_MatchCurrentJustifiedCheckpt_Bellatrix(t *testing.T) { + testtmpl.VerifyBeaconStateMatchCurrentJustifiedCheckptNative( + t, + func(cp *ethpb.Checkpoint) (state.BeaconState, error) { + return InitializeFromProtoBellatrix(ðpb.BeaconStateBellatrix{CurrentJustifiedCheckpoint: cp}) + }, + ) +} + +func TestBeaconState_MatchPreviousJustifiedCheckpt_Phase0(t *testing.T) { + testtmpl.VerifyBeaconStateMatchPreviousJustifiedCheckptNative( + t, + func(cp *ethpb.Checkpoint) (state.BeaconState, error) { + return InitializeFromProtoPhase0(ðpb.BeaconState{PreviousJustifiedCheckpoint: cp}) + }, + ) +} + +func TestBeaconState_MatchPreviousJustifiedCheckpt_Altair(t *testing.T) { + testtmpl.VerifyBeaconStateMatchPreviousJustifiedCheckptNative( + t, + func(cp *ethpb.Checkpoint) (state.BeaconState, error) { + return InitializeFromProtoAltair(ðpb.BeaconStateAltair{PreviousJustifiedCheckpoint: cp}) + }, + ) +} + +func TestBeaconState_MatchPreviousJustifiedCheckpt_Bellatrix(t *testing.T) { + testtmpl.VerifyBeaconStateMatchPreviousJustifiedCheckptNative( + t, + func(cp *ethpb.Checkpoint) (state.BeaconState, error) { + return InitializeFromProtoBellatrix(ðpb.BeaconStateBellatrix{PreviousJustifiedCheckpoint: cp}) + }, + ) +} + +func TestBeaconState_ValidatorByPubkey_Phase0(t *testing.T) { + testtmpl.VerifyBeaconStateValidatorByPubkey(t, func() (state.BeaconState, error) { + return InitializeFromProtoPhase0(ðpb.BeaconState{}) + }) +} + +func TestBeaconState_ValidatorByPubkey_Altair(t *testing.T) { + testtmpl.VerifyBeaconStateValidatorByPubkey(t, func() (state.BeaconState, error) { + return InitializeFromProtoAltair(ðpb.BeaconStateAltair{}) + }) +} + +func TestBeaconState_ValidatorByPubkey_Bellatrix(t *testing.T) { + testtmpl.VerifyBeaconStateValidatorByPubkey(t, func() (state.BeaconState, error) { + return InitializeFromProtoBellatrix(ðpb.BeaconStateBellatrix{}) + }) +} diff --git a/beacon-chain/state/state-native/v3/getters_validator.go b/beacon-chain/state/state-native/getters_validator.go similarity index 96% rename from beacon-chain/state/state-native/v3/getters_validator.go rename to beacon-chain/state/state-native/getters_validator.go index 108e345ac9..9a2706e208 100644 --- a/beacon-chain/state/state-native/v3/getters_validator.go +++ b/beacon-chain/state/state-native/getters_validator.go @@ -1,15 +1,15 @@ -package v3 +package state_native import ( "fmt" "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/beacon-chain/state" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/v1" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" types "github.com/prysmaticlabs/prysm/consensus-types/primitives" "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/runtime/version" ) // ValidatorIndexOutOfRangeError represents an error scenario where a validator does not exist @@ -111,7 +111,7 @@ func (b *BeaconState) ValidatorAtIndexReadOnly(idx types.ValidatorIndex) (state. b.lock.RLock() defer b.lock.RUnlock() - return v1.NewValidator(b.validators[idx]) + return NewValidator(b.validators[idx]) } // ValidatorIndexByPubkey returns a given validator by its 48-byte public key. @@ -164,7 +164,7 @@ func (b *BeaconState) ReadFromEveryValidator(f func(idx int, val state.ReadOnlyV b.lock.RUnlock() for i, v := range validators { - v, err := v1.NewValidator(v) + v, err := NewValidator(v) if err != nil { return err } @@ -250,6 +250,22 @@ func (b *BeaconState) slashingsVal() []uint64 { return res } +// InactivityScores of validators participating in consensus on the beacon chain. +func (b *BeaconState) InactivityScores() ([]uint64, error) { + if b.version == version.Phase0 { + return nil, errNotSupported("InactivityScores", b.version) + } + + if b.inactivityScores == nil { + return nil, nil + } + + b.lock.RLock() + defer b.lock.RUnlock() + + return b.inactivityScoresVal(), nil +} + // inactivityScoresVal of validators participating in consensus on the beacon chain. // This assumes that a lock is already held on BeaconState. func (b *BeaconState) inactivityScoresVal() []uint64 { @@ -261,15 +277,3 @@ func (b *BeaconState) inactivityScoresVal() []uint64 { copy(res, b.inactivityScores) return res } - -// InactivityScores of validators participating in consensus on the beacon chain. -func (b *BeaconState) InactivityScores() ([]uint64, error) { - if b.inactivityScores == nil { - return nil, nil - } - - b.lock.RLock() - defer b.lock.RUnlock() - - return b.inactivityScoresVal(), nil -} diff --git a/beacon-chain/state/state-native/getters_validator_test.go b/beacon-chain/state/state-native/getters_validator_test.go new file mode 100644 index 0000000000..b279c60670 --- /dev/null +++ b/beacon-chain/state/state-native/getters_validator_test.go @@ -0,0 +1,34 @@ +package state_native_test + +import ( + "testing" + + "github.com/prysmaticlabs/prysm/beacon-chain/state" + statenative "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native" + testtmpl "github.com/prysmaticlabs/prysm/beacon-chain/state/testing" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" +) + +func TestBeaconState_ValidatorAtIndexReadOnly_HandlesNilSlice_Phase0(t *testing.T) { + testtmpl.VerifyBeaconStateValidatorAtIndexReadOnlyHandlesNilSlice(t, func() (state.BeaconState, error) { + return statenative.InitializeFromProtoUnsafePhase0(ðpb.BeaconState{ + Validators: nil, + }) + }) +} + +func TestBeaconState_ValidatorAtIndexReadOnly_HandlesNilSlice_Altair(t *testing.T) { + testtmpl.VerifyBeaconStateValidatorAtIndexReadOnlyHandlesNilSlice(t, func() (state.BeaconState, error) { + return statenative.InitializeFromProtoUnsafeAltair(ðpb.BeaconStateAltair{ + Validators: nil, + }) + }) +} + +func TestBeaconState_ValidatorAtIndexReadOnly_HandlesNilSlice_Bellatrix(t *testing.T) { + testtmpl.VerifyBeaconStateValidatorAtIndexReadOnlyHandlesNilSlice(t, func() (state.BeaconState, error) { + return statenative.InitializeFromProtoUnsafeBellatrix(ðpb.BeaconStateBellatrix{ + Validators: nil, + }) + }) +} diff --git a/beacon-chain/state/state-native/hasher.go b/beacon-chain/state/state-native/hasher.go new file mode 100644 index 0000000000..ad4a76e12e --- /dev/null +++ b/beacon-chain/state/state-native/hasher.go @@ -0,0 +1,240 @@ +package state_native + +import ( + "context" + "encoding/binary" + + "github.com/pkg/errors" + nativetypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/types" + "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" + fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" + "github.com/prysmaticlabs/prysm/config/params" + "github.com/prysmaticlabs/prysm/crypto/hash" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/encoding/ssz" + "github.com/prysmaticlabs/prysm/runtime/version" + "go.opencensus.io/trace" +) + +// ComputeFieldRootsWithHasher hashes the provided state and returns its respective field roots. +func ComputeFieldRootsWithHasher(ctx context.Context, state *BeaconState) ([][]byte, error) { + _, span := trace.StartSpan(ctx, "ComputeFieldRootsWithHasher") + defer span.End() + + if state == nil { + return nil, errors.New("nil state") + } + hasher := hash.CustomSHA256Hasher() + var fieldRoots [][]byte + switch state.version { + case version.Phase0: + fieldRoots = make([][]byte, params.BeaconConfig().BeaconStateFieldCount) + case version.Altair: + fieldRoots = make([][]byte, params.BeaconConfig().BeaconStateAltairFieldCount) + case version.Bellatrix: + fieldRoots = make([][]byte, params.BeaconConfig().BeaconStateBellatrixFieldCount) + } + + // Genesis time root. + genesisRoot := ssz.Uint64Root(state.genesisTime) + fieldRoots[nativetypes.GenesisTime.RealPosition()] = genesisRoot[:] + + // Genesis validators root. + r := [32]byte{} + copy(r[:], state.genesisValidatorsRoot[:]) + fieldRoots[nativetypes.GenesisValidatorsRoot.RealPosition()] = r[:] + + // Slot root. + slotRoot := ssz.Uint64Root(uint64(state.slot)) + fieldRoots[nativetypes.Slot.RealPosition()] = slotRoot[:] + + // Fork data structure root. + forkHashTreeRoot, err := ssz.ForkRoot(state.fork) + if err != nil { + return nil, errors.Wrap(err, "could not compute fork merkleization") + } + fieldRoots[nativetypes.Fork.RealPosition()] = forkHashTreeRoot[:] + + // BeaconBlockHeader data structure root. + headerHashTreeRoot, err := stateutil.BlockHeaderRoot(state.latestBlockHeader) + if err != nil { + return nil, errors.Wrap(err, "could not compute block header merkleization") + } + fieldRoots[nativetypes.LatestBlockHeader.RealPosition()] = headerHashTreeRoot[:] + + // BlockRoots array root. + bRoots := make([][]byte, len(state.blockRoots)) + for i := range bRoots { + bRoots[i] = state.blockRoots[i][:] + } + blockRootsRoot, err := stateutil.ArraysRoot(bRoots, fieldparams.BlockRootsLength) + if err != nil { + return nil, errors.Wrap(err, "could not compute block roots merkleization") + } + fieldRoots[nativetypes.BlockRoots.RealPosition()] = blockRootsRoot[:] + + // StateRoots array root. + sRoots := make([][]byte, len(state.stateRoots)) + for i := range sRoots { + sRoots[i] = state.stateRoots[i][:] + } + stateRootsRoot, err := stateutil.ArraysRoot(sRoots, fieldparams.StateRootsLength) + if err != nil { + return nil, errors.Wrap(err, "could not compute state roots merkleization") + } + fieldRoots[nativetypes.StateRoots.RealPosition()] = stateRootsRoot[:] + + // HistoricalRoots slice root. + hRoots := make([][]byte, len(state.historicalRoots)) + for i := range hRoots { + hRoots[i] = state.historicalRoots[i][:] + } + historicalRootsRt, err := ssz.ByteArrayRootWithLimit(hRoots, fieldparams.HistoricalRootsLength) + if err != nil { + return nil, errors.Wrap(err, "could not compute historical roots merkleization") + } + fieldRoots[nativetypes.HistoricalRoots.RealPosition()] = historicalRootsRt[:] + + // Eth1Data data structure root. + eth1HashTreeRoot, err := stateutil.Eth1Root(hasher, state.eth1Data) + if err != nil { + return nil, errors.Wrap(err, "could not compute eth1data merkleization") + } + fieldRoots[nativetypes.Eth1Data.RealPosition()] = eth1HashTreeRoot[:] + + // Eth1DataVotes slice root. + eth1VotesRoot, err := stateutil.Eth1DataVotesRoot(state.eth1DataVotes) + if err != nil { + return nil, errors.Wrap(err, "could not compute eth1data votes merkleization") + } + fieldRoots[nativetypes.Eth1DataVotes.RealPosition()] = eth1VotesRoot[:] + + // Eth1DepositIndex root. + eth1DepositIndexBuf := make([]byte, 8) + binary.LittleEndian.PutUint64(eth1DepositIndexBuf, state.eth1DepositIndex) + eth1DepositBuf := bytesutil.ToBytes32(eth1DepositIndexBuf) + fieldRoots[nativetypes.Eth1DepositIndex.RealPosition()] = eth1DepositBuf[:] + + // Validators slice root. + validatorsRoot, err := stateutil.ValidatorRegistryRoot(state.validators) + if err != nil { + return nil, errors.Wrap(err, "could not compute validator registry merkleization") + } + fieldRoots[nativetypes.Validators.RealPosition()] = validatorsRoot[:] + + // Balances slice root. + balancesRoot, err := stateutil.Uint64ListRootWithRegistryLimit(state.balances) + if err != nil { + return nil, errors.Wrap(err, "could not compute validator balances merkleization") + } + fieldRoots[nativetypes.Balances.RealPosition()] = balancesRoot[:] + + // RandaoMixes array root. + mixes := make([][]byte, len(state.randaoMixes)) + for i := range mixes { + mixes[i] = state.randaoMixes[i][:] + } + randaoRootsRoot, err := stateutil.ArraysRoot(mixes, fieldparams.RandaoMixesLength) + if err != nil { + return nil, errors.Wrap(err, "could not compute randao roots merkleization") + } + fieldRoots[nativetypes.RandaoMixes.RealPosition()] = randaoRootsRoot[:] + + // Slashings array root. + slashingsRootsRoot, err := ssz.SlashingsRoot(state.slashings) + if err != nil { + return nil, errors.Wrap(err, "could not compute slashings merkleization") + } + fieldRoots[nativetypes.Slashings.RealPosition()] = slashingsRootsRoot[:] + + if state.version == version.Phase0 { + // PreviousEpochAttestations slice root. + prevAttsRoot, err := stateutil.EpochAttestationsRoot(state.previousEpochAttestations) + if err != nil { + return nil, errors.Wrap(err, "could not compute previous epoch attestations merkleization") + } + fieldRoots[nativetypes.PreviousEpochAttestations.RealPosition()] = prevAttsRoot[:] + + // CurrentEpochAttestations slice root. + currAttsRoot, err := stateutil.EpochAttestationsRoot(state.currentEpochAttestations) + if err != nil { + return nil, errors.Wrap(err, "could not compute current epoch attestations merkleization") + } + fieldRoots[nativetypes.CurrentEpochAttestations.RealPosition()] = currAttsRoot[:] + } + + if state.version == version.Altair || state.version == version.Bellatrix { + // PreviousEpochParticipation slice root. + prevParticipationRoot, err := stateutil.ParticipationBitsRoot(state.previousEpochParticipation) + if err != nil { + return nil, errors.Wrap(err, "could not compute previous epoch participation merkleization") + } + fieldRoots[nativetypes.PreviousEpochParticipationBits.RealPosition()] = prevParticipationRoot[:] + + // CurrentEpochParticipation slice root. + currParticipationRoot, err := stateutil.ParticipationBitsRoot(state.currentEpochParticipation) + if err != nil { + return nil, errors.Wrap(err, "could not compute current epoch participation merkleization") + } + fieldRoots[nativetypes.CurrentEpochParticipationBits.RealPosition()] = currParticipationRoot[:] + } + + // JustificationBits root. + justifiedBitsRoot := bytesutil.ToBytes32(state.justificationBits) + fieldRoots[nativetypes.JustificationBits.RealPosition()] = justifiedBitsRoot[:] + + // PreviousJustifiedCheckpoint data structure root. + prevCheckRoot, err := ssz.CheckpointRoot(hasher, state.previousJustifiedCheckpoint) + if err != nil { + return nil, errors.Wrap(err, "could not compute previous justified checkpoint merkleization") + } + fieldRoots[nativetypes.PreviousJustifiedCheckpoint.RealPosition()] = prevCheckRoot[:] + + // CurrentJustifiedCheckpoint data structure root. + currJustRoot, err := ssz.CheckpointRoot(hasher, state.currentJustifiedCheckpoint) + if err != nil { + return nil, errors.Wrap(err, "could not compute current justified checkpoint merkleization") + } + fieldRoots[nativetypes.CurrentJustifiedCheckpoint.RealPosition()] = currJustRoot[:] + + // FinalizedCheckpoint data structure root. + finalRoot, err := ssz.CheckpointRoot(hasher, state.finalizedCheckpoint) + if err != nil { + return nil, errors.Wrap(err, "could not compute finalized checkpoint merkleization") + } + fieldRoots[nativetypes.FinalizedCheckpoint.RealPosition()] = finalRoot[:] + + if state.version == version.Altair || state.version == version.Bellatrix { + // Inactivity scores root. + inactivityScoresRoot, err := stateutil.Uint64ListRootWithRegistryLimit(state.inactivityScores) + if err != nil { + return nil, errors.Wrap(err, "could not compute inactivityScoreRoot") + } + fieldRoots[nativetypes.InactivityScores.RealPosition()] = inactivityScoresRoot[:] + + // Current sync committee root. + currentSyncCommitteeRoot, err := stateutil.SyncCommitteeRoot(state.currentSyncCommittee) + if err != nil { + return nil, errors.Wrap(err, "could not compute sync committee merkleization") + } + fieldRoots[nativetypes.CurrentSyncCommittee.RealPosition()] = currentSyncCommitteeRoot[:] + + // Next sync committee root. + nextSyncCommitteeRoot, err := stateutil.SyncCommitteeRoot(state.nextSyncCommittee) + if err != nil { + return nil, errors.Wrap(err, "could not compute sync committee merkleization") + } + fieldRoots[nativetypes.NextSyncCommittee.RealPosition()] = nextSyncCommitteeRoot[:] + } + + if state.version == version.Bellatrix { + // Execution payload root. + executionPayloadRoot, err := state.latestExecutionPayloadHeader.HashTreeRoot() + if err != nil { + return nil, err + } + fieldRoots[nativetypes.LatestExecutionPayloadHeader.RealPosition()] = executionPayloadRoot[:] + } + + return fieldRoots, nil +} diff --git a/beacon-chain/state/state-native/hasher_test.go b/beacon-chain/state/state-native/hasher_test.go new file mode 100644 index 0000000000..045f94342c --- /dev/null +++ b/beacon-chain/state/state-native/hasher_test.go @@ -0,0 +1,355 @@ +package state_native_test + +import ( + "context" + "testing" + + "github.com/prysmaticlabs/go-bitfield" + state_native "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native" + v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + v2 "github.com/prysmaticlabs/prysm/beacon-chain/state/v2" + v3 "github.com/prysmaticlabs/prysm/beacon-chain/state/v3" + "github.com/prysmaticlabs/prysm/config/params" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/testing/assert" + "github.com/prysmaticlabs/prysm/testing/require" + "github.com/prysmaticlabs/prysm/testing/util" +) + +func TestComputeFieldRootsWithHasher_Phase0(t *testing.T) { + beaconState, err := util.NewBeaconState(util.FillRootsNaturalOpt) + require.NoError(t, err) + require.NoError(t, beaconState.SetGenesisTime(123)) + require.NoError(t, beaconState.SetGenesisValidatorsRoot(genesisValidatorsRoot())) + require.NoError(t, beaconState.SetSlot(123)) + require.NoError(t, beaconState.SetFork(fork())) + require.NoError(t, beaconState.SetLatestBlockHeader(latestBlockHeader())) + historicalRoots, err := util.PrepareRoots(int(params.BeaconConfig().SlotsPerHistoricalRoot)) + require.NoError(t, err) + require.NoError(t, beaconState.SetHistoricalRoots(historicalRoots)) + require.NoError(t, beaconState.SetEth1Data(eth1Data())) + require.NoError(t, beaconState.SetEth1DataVotes([]*ethpb.Eth1Data{eth1Data()})) + require.NoError(t, beaconState.SetEth1DepositIndex(123)) + require.NoError(t, beaconState.SetValidators([]*ethpb.Validator{validator()})) + require.NoError(t, beaconState.SetBalances([]uint64{1, 2, 3})) + randaoMixes, err := util.PrepareRoots(int(params.BeaconConfig().EpochsPerHistoricalVector)) + require.NoError(t, err) + require.NoError(t, beaconState.SetRandaoMixes(randaoMixes)) + require.NoError(t, beaconState.SetSlashings([]uint64{1, 2, 3})) + require.NoError(t, beaconState.AppendPreviousEpochAttestations(pendingAttestation("previous"))) + require.NoError(t, beaconState.AppendCurrentEpochAttestations(pendingAttestation("current"))) + require.NoError(t, beaconState.SetJustificationBits(justificationBits())) + require.NoError(t, beaconState.SetPreviousJustifiedCheckpoint(checkpoint("previous"))) + require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(checkpoint("current"))) + require.NoError(t, beaconState.SetFinalizedCheckpoint(checkpoint("finalized"))) + + v1State, ok := beaconState.(*v1.BeaconState) + require.Equal(t, true, ok) + protoState, ok := v1State.InnerStateUnsafe().(*ethpb.BeaconState) + require.Equal(t, true, ok) + initState, err := state_native.InitializeFromProtoPhase0(protoState) + require.NoError(t, err) + s, ok := initState.(*state_native.BeaconState) + require.Equal(t, true, ok) + root, err := state_native.ComputeFieldRootsWithHasher(context.Background(), s) + require.NoError(t, err) + expected := [][]byte{ + {0x7b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, + {0x67, 0x76, 0x72, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, + {0x7b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, + {0x58, 0xba, 0xf, 0x9b, 0x4f, 0x63, 0x1c, 0xa6, 0x19, 0xb1, 0xa2, 0x1f, 0xd1, 0x29, 0xc7, 0x67, 0x9c, 0x32, 0x4, 0x1f, 0xcf, 0x4e, 0x64, 0x9b, 0x8f, 0x21, 0xb4, 0xe6, 0xa5, 0xc9, 0xc, 0x38}, + {0x8b, 0x5, 0x59, 0x78, 0xed, 0xbe, 0x2c, 0xde, 0xa6, 0xf, 0x52, 0xdc, 0x16, 0x83, 0xa0, 0x5d, 0x8, 0xc3, 0x37, 0x91, 0x3a, 0xf6, 0xfa, 0x6, 0x62, 0xc9, 0x6, 0xb1, 0x41, 0x48, 0xaf, 0xec}, + {0xcc, 0xa1, 0x69, 0xa8, 0x8b, 0x1e, 0x49, 0x5, 0x1f, 0xe4, 0xd8, 0xff, 0x82, 0xa2, 0x2e, 0xf0, 0x54, 0xd1, 0x13, 0xc9, 0x8e, 0xb9, 0x82, 0xa6, 0x9e, 0x42, 0x2, 0xec, 0x97, 0x6f, 0x33, 0x88}, + {0xcc, 0xa1, 0x69, 0xa8, 0x8b, 0x1e, 0x49, 0x5, 0x1f, 0xe4, 0xd8, 0xff, 0x82, 0xa2, 0x2e, 0xf0, 0x54, 0xd1, 0x13, 0xc9, 0x8e, 0xb9, 0x82, 0xa6, 0x9e, 0x42, 0x2, 0xec, 0x97, 0x6f, 0x33, 0x88}, + {0xf, 0xad, 0xd3, 0x92, 0x4b, 0xda, 0xfa, 0xc6, 0x61, 0x50, 0xb7, 0xdf, 0x5f, 0x2c, 0xd0, 0x94, 0xc3, 0xaf, 0x41, 0x9d, 0xa, 0xea, 0x50, 0x96, 0x82, 0x62, 0x1c, 0x72, 0x26, 0x20, 0x6b, 0xac}, + {0xc9, 0x4e, 0x2c, 0xb0, 0x20, 0xe3, 0xe7, 0x8c, 0x5c, 0xbd, 0xeb, 0x9b, 0xa5, 0x7b, 0x53, 0x50, 0xca, 0xfe, 0xe9, 0x48, 0x9e, 0x8d, 0xf8, 0x4a, 0xe6, 0x8d, 0x9c, 0x97, 0x81, 0x74, 0xb, 0x5e}, + {0x71, 0x52, 0xd2, 0x9b, 0x87, 0x3c, 0x8a, 0xd9, 0x51, 0x55, 0xc0, 0x42, 0xb, 0xc4, 0x12, 0xa4, 0x79, 0xf5, 0x7d, 0x37, 0x16, 0xf4, 0x90, 0x72, 0x5d, 0xe0, 0x34, 0xb4, 0x2, 0x8c, 0x39, 0xe4}, + {0x7b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, + {0xf, 0xf7, 0x4f, 0xe1, 0xa9, 0x72, 0x9c, 0x95, 0xf0, 0xe1, 0xde, 0xa4, 0x32, 0xc, 0x67, 0x52, 0x23, 0x13, 0x9e, 0xe2, 0x40, 0x8d, 0xf6, 0x18, 0x57, 0xf0, 0x1a, 0x4a, 0xad, 0x46, 0xce, 0x42}, + {0xf9, 0x11, 0x2c, 0xc2, 0x71, 0x70, 0xde, 0x47, 0x26, 0xeb, 0x26, 0xd4, 0xa4, 0xe8, 0x68, 0xb, 0x16, 0xa2, 0x6e, 0x52, 0x54, 0xe, 0x5c, 0x83, 0x17, 0x3, 0xea, 0xdd, 0xd5, 0xa7, 0xb2, 0x3f}, + {0x64, 0xbd, 0x40, 0xa7, 0x10, 0x44, 0x84, 0xed, 0xf3, 0x5f, 0xc3, 0x5d, 0x7b, 0xbe, 0xe8, 0x75, 0xbf, 0x66, 0xcb, 0xce, 0x77, 0xfa, 0x0, 0x3, 0xdd, 0xfb, 0x80, 0xd2, 0x77, 0x1b, 0xc2, 0x8}, + {0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, + {0x54, 0xd3, 0xce, 0x8a, 0x3f, 0xfd, 0x21, 0x3a, 0xb4, 0xa6, 0xd, 0xb, 0x9f, 0xf2, 0x88, 0xf0, 0xb1, 0x44, 0x9d, 0xb1, 0x2, 0x95, 0x67, 0xdf, 0x6f, 0x28, 0xa9, 0x68, 0xcd, 0xaa, 0x8c, 0x54}, + {0xeb, 0x8, 0xb4, 0x1b, 0x76, 0xa2, 0x23, 0xbb, 0x4a, 0xd3, 0x78, 0xca, 0x2e, 0xe8, 0x2c, 0xa1, 0xbf, 0x45, 0xf2, 0x58, 0xdf, 0x39, 0xdf, 0x43, 0x40, 0xb, 0x96, 0xcf, 0xfd, 0x9a, 0x87, 0x85}, + {0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, + {0x76, 0x88, 0xa0, 0x68, 0x45, 0x25, 0x8f, 0xd5, 0xf9, 0xb2, 0xb0, 0x42, 0x68, 0x6b, 0x51, 0xcc, 0x29, 0x94, 0x63, 0x85, 0xec, 0xf5, 0x47, 0xf0, 0x9c, 0x46, 0x86, 0xa9, 0x99, 0x7d, 0x29, 0x6c}, + {0x41, 0x44, 0x52, 0xff, 0x8c, 0xa6, 0xb3, 0x2e, 0xcc, 0x5e, 0x63, 0x8f, 0x8e, 0x7d, 0xe7, 0x52, 0x42, 0x94, 0x55, 0x2f, 0x89, 0xdd, 0x1e, 0x3c, 0xb0, 0xf4, 0x51, 0x51, 0x36, 0x81, 0x72, 0x1}, + {0xa9, 0xbb, 0x6a, 0x1f, 0x5d, 0x86, 0x7d, 0xa7, 0x5a, 0x7d, 0x9d, 0x8d, 0xc0, 0x15, 0xb7, 0x0, 0xee, 0xa9, 0x68, 0x51, 0x88, 0x57, 0x5a, 0xd9, 0x4e, 0x1d, 0x8e, 0x44, 0xbf, 0xdc, 0x73, 0xff}, + } + assert.DeepEqual(t, expected, root) +} + +func TestComputeFieldRootsWithHasher_Altair(t *testing.T) { + beaconState, err := util.NewBeaconStateAltair(util.FillRootsNaturalOptAltair) + require.NoError(t, err) + require.NoError(t, beaconState.SetGenesisTime(123)) + require.NoError(t, beaconState.SetGenesisValidatorsRoot(genesisValidatorsRoot())) + require.NoError(t, beaconState.SetSlot(123)) + require.NoError(t, beaconState.SetFork(fork())) + require.NoError(t, beaconState.SetLatestBlockHeader(latestBlockHeader())) + historicalRoots, err := util.PrepareRoots(int(params.BeaconConfig().SlotsPerHistoricalRoot)) + require.NoError(t, err) + require.NoError(t, beaconState.SetHistoricalRoots(historicalRoots)) + require.NoError(t, beaconState.SetEth1Data(eth1Data())) + require.NoError(t, beaconState.SetEth1DataVotes([]*ethpb.Eth1Data{eth1Data()})) + require.NoError(t, beaconState.SetEth1DepositIndex(123)) + require.NoError(t, beaconState.SetValidators([]*ethpb.Validator{validator()})) + require.NoError(t, beaconState.SetBalances([]uint64{1, 2, 3})) + randaoMixes, err := util.PrepareRoots(int(params.BeaconConfig().EpochsPerHistoricalVector)) + require.NoError(t, err) + require.NoError(t, beaconState.SetRandaoMixes(randaoMixes)) + require.NoError(t, beaconState.SetSlashings([]uint64{1, 2, 3})) + require.NoError(t, beaconState.SetPreviousParticipationBits([]byte{1, 2, 3})) + require.NoError(t, beaconState.SetCurrentParticipationBits([]byte{1, 2, 3})) + require.NoError(t, beaconState.SetJustificationBits(justificationBits())) + require.NoError(t, beaconState.SetPreviousJustifiedCheckpoint(checkpoint("previous"))) + require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(checkpoint("current"))) + require.NoError(t, beaconState.SetFinalizedCheckpoint(checkpoint("finalized"))) + require.NoError(t, beaconState.SetInactivityScores([]uint64{1, 2, 3})) + require.NoError(t, beaconState.SetCurrentSyncCommittee(syncCommittee("current"))) + require.NoError(t, beaconState.SetNextSyncCommittee(syncCommittee("next"))) + + v1State, ok := beaconState.(*v2.BeaconState) + require.Equal(t, true, ok) + protoState, ok := v1State.InnerStateUnsafe().(*ethpb.BeaconStateAltair) + require.Equal(t, true, ok) + initState, err := state_native.InitializeFromProtoAltair(protoState) + require.NoError(t, err) + s, ok := initState.(*state_native.BeaconState) + require.Equal(t, true, ok) + + root, err := state_native.ComputeFieldRootsWithHasher(context.Background(), s) + require.NoError(t, err) + expected := [][]byte{ + {0x7b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, + {0x67, 0x76, 0x72, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, + {0x7b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, + {0x58, 0xba, 0xf, 0x9b, 0x4f, 0x63, 0x1c, 0xa6, 0x19, 0xb1, 0xa2, 0x1f, 0xd1, 0x29, 0xc7, 0x67, 0x9c, 0x32, 0x4, 0x1f, 0xcf, 0x4e, 0x64, 0x9b, 0x8f, 0x21, 0xb4, 0xe6, 0xa5, 0xc9, 0xc, 0x38}, + {0x8b, 0x5, 0x59, 0x78, 0xed, 0xbe, 0x2c, 0xde, 0xa6, 0xf, 0x52, 0xdc, 0x16, 0x83, 0xa0, 0x5d, 0x8, 0xc3, 0x37, 0x91, 0x3a, 0xf6, 0xfa, 0x6, 0x62, 0xc9, 0x6, 0xb1, 0x41, 0x48, 0xaf, 0xec}, + {0xcc, 0xa1, 0x69, 0xa8, 0x8b, 0x1e, 0x49, 0x5, 0x1f, 0xe4, 0xd8, 0xff, 0x82, 0xa2, 0x2e, 0xf0, 0x54, 0xd1, 0x13, 0xc9, 0x8e, 0xb9, 0x82, 0xa6, 0x9e, 0x42, 0x2, 0xec, 0x97, 0x6f, 0x33, 0x88}, + {0xcc, 0xa1, 0x69, 0xa8, 0x8b, 0x1e, 0x49, 0x5, 0x1f, 0xe4, 0xd8, 0xff, 0x82, 0xa2, 0x2e, 0xf0, 0x54, 0xd1, 0x13, 0xc9, 0x8e, 0xb9, 0x82, 0xa6, 0x9e, 0x42, 0x2, 0xec, 0x97, 0x6f, 0x33, 0x88}, + {0xf, 0xad, 0xd3, 0x92, 0x4b, 0xda, 0xfa, 0xc6, 0x61, 0x50, 0xb7, 0xdf, 0x5f, 0x2c, 0xd0, 0x94, 0xc3, 0xaf, 0x41, 0x9d, 0xa, 0xea, 0x50, 0x96, 0x82, 0x62, 0x1c, 0x72, 0x26, 0x20, 0x6b, 0xac}, + {0xc9, 0x4e, 0x2c, 0xb0, 0x20, 0xe3, 0xe7, 0x8c, 0x5c, 0xbd, 0xeb, 0x9b, 0xa5, 0x7b, 0x53, 0x50, 0xca, 0xfe, 0xe9, 0x48, 0x9e, 0x8d, 0xf8, 0x4a, 0xe6, 0x8d, 0x9c, 0x97, 0x81, 0x74, 0xb, 0x5e}, + {0x71, 0x52, 0xd2, 0x9b, 0x87, 0x3c, 0x8a, 0xd9, 0x51, 0x55, 0xc0, 0x42, 0xb, 0xc4, 0x12, 0xa4, 0x79, 0xf5, 0x7d, 0x37, 0x16, 0xf4, 0x90, 0x72, 0x5d, 0xe0, 0x34, 0xb4, 0x2, 0x8c, 0x39, 0xe4}, + {0x7b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, + {0xf, 0xf7, 0x4f, 0xe1, 0xa9, 0x72, 0x9c, 0x95, 0xf0, 0xe1, 0xde, 0xa4, 0x32, 0xc, 0x67, 0x52, 0x23, 0x13, 0x9e, 0xe2, 0x40, 0x8d, 0xf6, 0x18, 0x57, 0xf0, 0x1a, 0x4a, 0xad, 0x46, 0xce, 0x42}, + {0xf9, 0x11, 0x2c, 0xc2, 0x71, 0x70, 0xde, 0x47, 0x26, 0xeb, 0x26, 0xd4, 0xa4, 0xe8, 0x68, 0xb, 0x16, 0xa2, 0x6e, 0x52, 0x54, 0xe, 0x5c, 0x83, 0x17, 0x3, 0xea, 0xdd, 0xd5, 0xa7, 0xb2, 0x3f}, + {0x64, 0xbd, 0x40, 0xa7, 0x10, 0x44, 0x84, 0xed, 0xf3, 0x5f, 0xc3, 0x5d, 0x7b, 0xbe, 0xe8, 0x75, 0xbf, 0x66, 0xcb, 0xce, 0x77, 0xfa, 0x0, 0x3, 0xdd, 0xfb, 0x80, 0xd2, 0x77, 0x1b, 0xc2, 0x8}, + {0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, + {0x75, 0xb2, 0xae, 0x1d, 0xd8, 0xca, 0xe6, 0x4d, 0xa8, 0xc5, 0xc9, 0x19, 0x8, 0x96, 0xaf, 0x9b, 0xe6, 0xf6, 0x99, 0xb9, 0x58, 0x56, 0x5b, 0x25, 0xea, 0x9c, 0x86, 0x5e, 0x96, 0x6a, 0x48, 0xb}, + {0x75, 0xb2, 0xae, 0x1d, 0xd8, 0xca, 0xe6, 0x4d, 0xa8, 0xc5, 0xc9, 0x19, 0x8, 0x96, 0xaf, 0x9b, 0xe6, 0xf6, 0x99, 0xb9, 0x58, 0x56, 0x5b, 0x25, 0xea, 0x9c, 0x86, 0x5e, 0x96, 0x6a, 0x48, 0xb}, + {0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, + {0x76, 0x88, 0xa0, 0x68, 0x45, 0x25, 0x8f, 0xd5, 0xf9, 0xb2, 0xb0, 0x42, 0x68, 0x6b, 0x51, 0xcc, 0x29, 0x94, 0x63, 0x85, 0xec, 0xf5, 0x47, 0xf0, 0x9c, 0x46, 0x86, 0xa9, 0x99, 0x7d, 0x29, 0x6c}, + {0x41, 0x44, 0x52, 0xff, 0x8c, 0xa6, 0xb3, 0x2e, 0xcc, 0x5e, 0x63, 0x8f, 0x8e, 0x7d, 0xe7, 0x52, 0x42, 0x94, 0x55, 0x2f, 0x89, 0xdd, 0x1e, 0x3c, 0xb0, 0xf4, 0x51, 0x51, 0x36, 0x81, 0x72, 0x1}, + {0xa9, 0xbb, 0x6a, 0x1f, 0x5d, 0x86, 0x7d, 0xa7, 0x5a, 0x7d, 0x9d, 0x8d, 0xc0, 0x15, 0xb7, 0x0, 0xee, 0xa9, 0x68, 0x51, 0x88, 0x57, 0x5a, 0xd9, 0x4e, 0x1d, 0x8e, 0x44, 0xbf, 0xdc, 0x73, 0xff}, + {0xf9, 0x11, 0x2c, 0xc2, 0x71, 0x70, 0xde, 0x47, 0x26, 0xeb, 0x26, 0xd4, 0xa4, 0xe8, 0x68, 0xb, 0x16, 0xa2, 0x6e, 0x52, 0x54, 0xe, 0x5c, 0x83, 0x17, 0x3, 0xea, 0xdd, 0xd5, 0xa7, 0xb2, 0x3f}, + {0x3d, 0xf3, 0x66, 0xd4, 0x12, 0x40, 0x3f, 0x28, 0xeb, 0xe4, 0x19, 0x59, 0xae, 0xab, 0x4d, 0xf3, 0x98, 0x88, 0x7f, 0x1e, 0x58, 0xa, 0x5d, 0xd4, 0xeb, 0xe5, 0x5d, 0x3d, 0x11, 0x70, 0x24, 0x76}, + {0xd6, 0x4c, 0xb1, 0xac, 0x61, 0x7, 0x26, 0xbb, 0xd3, 0x27, 0x2a, 0xcd, 0xdd, 0x55, 0xf, 0x2b, 0x6a, 0xe8, 0x1, 0x31, 0x48, 0x66, 0x2f, 0x98, 0x7b, 0x6d, 0x27, 0x69, 0xd9, 0x40, 0xcc, 0x37}, + } + assert.DeepEqual(t, expected, root) +} + +func TestComputeFieldRootsWithHasher_Bellatrix(t *testing.T) { + beaconState, err := util.NewBeaconStateBellatrix(util.FillRootsNaturalOptBellatrix) + require.NoError(t, err) + require.NoError(t, beaconState.SetGenesisTime(123)) + require.NoError(t, beaconState.SetGenesisValidatorsRoot(genesisValidatorsRoot())) + require.NoError(t, beaconState.SetSlot(123)) + require.NoError(t, beaconState.SetFork(fork())) + require.NoError(t, beaconState.SetLatestBlockHeader(latestBlockHeader())) + historicalRoots, err := util.PrepareRoots(int(params.BeaconConfig().SlotsPerHistoricalRoot)) + require.NoError(t, err) + require.NoError(t, beaconState.SetHistoricalRoots(historicalRoots)) + require.NoError(t, beaconState.SetEth1Data(eth1Data())) + require.NoError(t, beaconState.SetEth1DataVotes([]*ethpb.Eth1Data{eth1Data()})) + require.NoError(t, beaconState.SetEth1DepositIndex(123)) + require.NoError(t, beaconState.SetValidators([]*ethpb.Validator{validator()})) + require.NoError(t, beaconState.SetBalances([]uint64{1, 2, 3})) + randaoMixes, err := util.PrepareRoots(int(params.BeaconConfig().EpochsPerHistoricalVector)) + require.NoError(t, err) + require.NoError(t, beaconState.SetRandaoMixes(randaoMixes)) + require.NoError(t, beaconState.SetSlashings([]uint64{1, 2, 3})) + require.NoError(t, beaconState.SetPreviousParticipationBits([]byte{1, 2, 3})) + require.NoError(t, beaconState.SetCurrentParticipationBits([]byte{1, 2, 3})) + require.NoError(t, beaconState.SetJustificationBits(justificationBits())) + require.NoError(t, beaconState.SetPreviousJustifiedCheckpoint(checkpoint("previous"))) + require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(checkpoint("current"))) + require.NoError(t, beaconState.SetFinalizedCheckpoint(checkpoint("finalized"))) + require.NoError(t, beaconState.SetInactivityScores([]uint64{1, 2, 3})) + require.NoError(t, beaconState.SetCurrentSyncCommittee(syncCommittee("current"))) + require.NoError(t, beaconState.SetNextSyncCommittee(syncCommittee("next"))) + require.NoError(t, beaconState.SetLatestExecutionPayloadHeader(executionPayloadHeader())) + + v1State, ok := beaconState.(*v3.BeaconState) + require.Equal(t, true, ok) + protoState, ok := v1State.InnerStateUnsafe().(*ethpb.BeaconStateBellatrix) + require.Equal(t, true, ok) + initState, err := state_native.InitializeFromProtoBellatrix(protoState) + require.NoError(t, err) + s, ok := initState.(*state_native.BeaconState) + require.Equal(t, true, ok) + + root, err := state_native.ComputeFieldRootsWithHasher(context.Background(), s) + require.NoError(t, err) + expected := [][]byte{ + {0x7b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, + {0x67, 0x76, 0x72, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, + {0x7b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, + {0x58, 0xba, 0xf, 0x9b, 0x4f, 0x63, 0x1c, 0xa6, 0x19, 0xb1, 0xa2, 0x1f, 0xd1, 0x29, 0xc7, 0x67, 0x9c, 0x32, 0x4, 0x1f, 0xcf, 0x4e, 0x64, 0x9b, 0x8f, 0x21, 0xb4, 0xe6, 0xa5, 0xc9, 0xc, 0x38}, + {0x8b, 0x5, 0x59, 0x78, 0xed, 0xbe, 0x2c, 0xde, 0xa6, 0xf, 0x52, 0xdc, 0x16, 0x83, 0xa0, 0x5d, 0x8, 0xc3, 0x37, 0x91, 0x3a, 0xf6, 0xfa, 0x6, 0x62, 0xc9, 0x6, 0xb1, 0x41, 0x48, 0xaf, 0xec}, + {0xcc, 0xa1, 0x69, 0xa8, 0x8b, 0x1e, 0x49, 0x5, 0x1f, 0xe4, 0xd8, 0xff, 0x82, 0xa2, 0x2e, 0xf0, 0x54, 0xd1, 0x13, 0xc9, 0x8e, 0xb9, 0x82, 0xa6, 0x9e, 0x42, 0x2, 0xec, 0x97, 0x6f, 0x33, 0x88}, + {0xcc, 0xa1, 0x69, 0xa8, 0x8b, 0x1e, 0x49, 0x5, 0x1f, 0xe4, 0xd8, 0xff, 0x82, 0xa2, 0x2e, 0xf0, 0x54, 0xd1, 0x13, 0xc9, 0x8e, 0xb9, 0x82, 0xa6, 0x9e, 0x42, 0x2, 0xec, 0x97, 0x6f, 0x33, 0x88}, + {0xf, 0xad, 0xd3, 0x92, 0x4b, 0xda, 0xfa, 0xc6, 0x61, 0x50, 0xb7, 0xdf, 0x5f, 0x2c, 0xd0, 0x94, 0xc3, 0xaf, 0x41, 0x9d, 0xa, 0xea, 0x50, 0x96, 0x82, 0x62, 0x1c, 0x72, 0x26, 0x20, 0x6b, 0xac}, + {0xc9, 0x4e, 0x2c, 0xb0, 0x20, 0xe3, 0xe7, 0x8c, 0x5c, 0xbd, 0xeb, 0x9b, 0xa5, 0x7b, 0x53, 0x50, 0xca, 0xfe, 0xe9, 0x48, 0x9e, 0x8d, 0xf8, 0x4a, 0xe6, 0x8d, 0x9c, 0x97, 0x81, 0x74, 0xb, 0x5e}, + {0x71, 0x52, 0xd2, 0x9b, 0x87, 0x3c, 0x8a, 0xd9, 0x51, 0x55, 0xc0, 0x42, 0xb, 0xc4, 0x12, 0xa4, 0x79, 0xf5, 0x7d, 0x37, 0x16, 0xf4, 0x90, 0x72, 0x5d, 0xe0, 0x34, 0xb4, 0x2, 0x8c, 0x39, 0xe4}, + {0x7b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, + {0xf, 0xf7, 0x4f, 0xe1, 0xa9, 0x72, 0x9c, 0x95, 0xf0, 0xe1, 0xde, 0xa4, 0x32, 0xc, 0x67, 0x52, 0x23, 0x13, 0x9e, 0xe2, 0x40, 0x8d, 0xf6, 0x18, 0x57, 0xf0, 0x1a, 0x4a, 0xad, 0x46, 0xce, 0x42}, + {0xf9, 0x11, 0x2c, 0xc2, 0x71, 0x70, 0xde, 0x47, 0x26, 0xeb, 0x26, 0xd4, 0xa4, 0xe8, 0x68, 0xb, 0x16, 0xa2, 0x6e, 0x52, 0x54, 0xe, 0x5c, 0x83, 0x17, 0x3, 0xea, 0xdd, 0xd5, 0xa7, 0xb2, 0x3f}, + {0x64, 0xbd, 0x40, 0xa7, 0x10, 0x44, 0x84, 0xed, 0xf3, 0x5f, 0xc3, 0x5d, 0x7b, 0xbe, 0xe8, 0x75, 0xbf, 0x66, 0xcb, 0xce, 0x77, 0xfa, 0x0, 0x3, 0xdd, 0xfb, 0x80, 0xd2, 0x77, 0x1b, 0xc2, 0x8}, + {0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, + {0x75, 0xb2, 0xae, 0x1d, 0xd8, 0xca, 0xe6, 0x4d, 0xa8, 0xc5, 0xc9, 0x19, 0x8, 0x96, 0xaf, 0x9b, 0xe6, 0xf6, 0x99, 0xb9, 0x58, 0x56, 0x5b, 0x25, 0xea, 0x9c, 0x86, 0x5e, 0x96, 0x6a, 0x48, 0xb}, + {0x75, 0xb2, 0xae, 0x1d, 0xd8, 0xca, 0xe6, 0x4d, 0xa8, 0xc5, 0xc9, 0x19, 0x8, 0x96, 0xaf, 0x9b, 0xe6, 0xf6, 0x99, 0xb9, 0x58, 0x56, 0x5b, 0x25, 0xea, 0x9c, 0x86, 0x5e, 0x96, 0x6a, 0x48, 0xb}, + {0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, + {0x76, 0x88, 0xa0, 0x68, 0x45, 0x25, 0x8f, 0xd5, 0xf9, 0xb2, 0xb0, 0x42, 0x68, 0x6b, 0x51, 0xcc, 0x29, 0x94, 0x63, 0x85, 0xec, 0xf5, 0x47, 0xf0, 0x9c, 0x46, 0x86, 0xa9, 0x99, 0x7d, 0x29, 0x6c}, + {0x41, 0x44, 0x52, 0xff, 0x8c, 0xa6, 0xb3, 0x2e, 0xcc, 0x5e, 0x63, 0x8f, 0x8e, 0x7d, 0xe7, 0x52, 0x42, 0x94, 0x55, 0x2f, 0x89, 0xdd, 0x1e, 0x3c, 0xb0, 0xf4, 0x51, 0x51, 0x36, 0x81, 0x72, 0x1}, + {0xa9, 0xbb, 0x6a, 0x1f, 0x5d, 0x86, 0x7d, 0xa7, 0x5a, 0x7d, 0x9d, 0x8d, 0xc0, 0x15, 0xb7, 0x0, 0xee, 0xa9, 0x68, 0x51, 0x88, 0x57, 0x5a, 0xd9, 0x4e, 0x1d, 0x8e, 0x44, 0xbf, 0xdc, 0x73, 0xff}, + {0xf9, 0x11, 0x2c, 0xc2, 0x71, 0x70, 0xde, 0x47, 0x26, 0xeb, 0x26, 0xd4, 0xa4, 0xe8, 0x68, 0xb, 0x16, 0xa2, 0x6e, 0x52, 0x54, 0xe, 0x5c, 0x83, 0x17, 0x3, 0xea, 0xdd, 0xd5, 0xa7, 0xb2, 0x3f}, + {0x3d, 0xf3, 0x66, 0xd4, 0x12, 0x40, 0x3f, 0x28, 0xeb, 0xe4, 0x19, 0x59, 0xae, 0xab, 0x4d, 0xf3, 0x98, 0x88, 0x7f, 0x1e, 0x58, 0xa, 0x5d, 0xd4, 0xeb, 0xe5, 0x5d, 0x3d, 0x11, 0x70, 0x24, 0x76}, + {0xd6, 0x4c, 0xb1, 0xac, 0x61, 0x7, 0x26, 0xbb, 0xd3, 0x27, 0x2a, 0xcd, 0xdd, 0x55, 0xf, 0x2b, 0x6a, 0xe8, 0x1, 0x31, 0x48, 0x66, 0x2f, 0x98, 0x7b, 0x6d, 0x27, 0x69, 0xd9, 0x40, 0xcc, 0x37}, + {0xbc, 0xbb, 0x39, 0x57, 0x61, 0x1d, 0x54, 0xd6, 0x1b, 0xfe, 0x7a, 0xbd, 0x29, 0x52, 0x57, 0xdd, 0x19, 0x1, 0x89, 0x22, 0x7d, 0xdf, 0x7b, 0x53, 0x9f, 0xb, 0x46, 0x5, 0x9f, 0x80, 0xcc, 0x8e}, + } + assert.DeepEqual(t, expected, root) +} + +func genesisValidatorsRoot() []byte { + gvr := bytesutil.ToBytes32([]byte("gvr")) + return gvr[:] +} + +func fork() *ethpb.Fork { + prev := bytesutil.ToBytes4([]byte("prev")) + curr := bytesutil.ToBytes4([]byte("curr")) + return ðpb.Fork{ + PreviousVersion: prev[:], + CurrentVersion: curr[:], + Epoch: 123, + } +} + +func latestBlockHeader() *ethpb.BeaconBlockHeader { + pr := bytesutil.ToBytes32([]byte("parent")) + sr := bytesutil.ToBytes32([]byte("state")) + br := bytesutil.ToBytes32([]byte("body")) + return ðpb.BeaconBlockHeader{ + Slot: 123, + ProposerIndex: 123, + ParentRoot: pr[:], + StateRoot: sr[:], + BodyRoot: br[:], + } +} + +func eth1Data() *ethpb.Eth1Data { + dr := bytesutil.ToBytes32([]byte("deposit")) + bh := bytesutil.ToBytes32([]byte("block")) + return ðpb.Eth1Data{ + DepositRoot: dr[:], + DepositCount: 123, + BlockHash: bh[:], + } +} + +func validator() *ethpb.Validator { + pk := bytesutil.ToBytes48([]byte("public")) + wc := bytesutil.ToBytes32([]byte("withdrawal")) + return ðpb.Validator{ + PublicKey: pk[:], + WithdrawalCredentials: wc[:], + EffectiveBalance: 123, + Slashed: true, + ActivationEligibilityEpoch: 123, + ActivationEpoch: 123, + ExitEpoch: 123, + WithdrawableEpoch: 123, + } +} + +func pendingAttestation(prefix string) *ethpb.PendingAttestation { + bbr := bytesutil.ToBytes32([]byte(prefix + "beacon")) + r := bytesutil.ToBytes32([]byte(prefix + "root")) + return ðpb.PendingAttestation{ + AggregationBits: bitfield.Bitlist{0x00, 0xFF, 0xFF, 0xFF}, + Data: ðpb.AttestationData{ + Slot: 123, + CommitteeIndex: 123, + BeaconBlockRoot: bbr[:], + Source: ðpb.Checkpoint{ + Epoch: 123, + Root: r[:], + }, + Target: ðpb.Checkpoint{ + Epoch: 123, + Root: r[:], + }, + }, + InclusionDelay: 123, + ProposerIndex: 123, + } +} + +func justificationBits() bitfield.Bitvector4 { + v := bitfield.NewBitvector4() + v.SetBitAt(1, true) + return v +} + +func checkpoint(prefix string) *ethpb.Checkpoint { + r := bytesutil.ToBytes32([]byte(prefix + "root")) + return ðpb.Checkpoint{ + Epoch: 123, + Root: r[:], + } +} + +func syncCommittee(prefix string) *ethpb.SyncCommittee { + pubkeys := make([][]byte, params.BeaconConfig().SyncCommitteeSize) + for i := range pubkeys { + key := bytesutil.ToBytes48([]byte(prefix + "pubkey")) + pubkeys[i] = key[:] + } + agg := bytesutil.ToBytes48([]byte(prefix + "aggregate")) + return ðpb.SyncCommittee{ + Pubkeys: pubkeys, + AggregatePubkey: agg[:], + } +} + +func executionPayloadHeader() *ethpb.ExecutionPayloadHeader { + ph := bytesutil.ToBytes32([]byte("parent")) + fr := bytesutil.PadTo([]byte("fee"), 20) + sr := bytesutil.ToBytes32([]byte("state")) + rr := bytesutil.ToBytes32([]byte("receipts")) + lb := bytesutil.PadTo([]byte("logs"), 256) + pr := bytesutil.ToBytes32([]byte("prev")) + ed := bytesutil.ToBytes32([]byte("extra")) + bf := bytesutil.ToBytes32([]byte("base")) + bh := bytesutil.ToBytes32([]byte("block")) + tr := bytesutil.ToBytes32([]byte("transactions")) + return ðpb.ExecutionPayloadHeader{ + ParentHash: ph[:], + FeeRecipient: fr, + StateRoot: sr[:], + ReceiptsRoot: rr[:], + LogsBloom: lb, + PrevRandao: pr[:], + BlockNumber: 0, + GasLimit: 0, + GasUsed: 0, + Timestamp: 0, + ExtraData: ed[:], + BaseFeePerGas: bf[:], + BlockHash: bh[:], + TransactionsRoot: tr[:], + } +} diff --git a/beacon-chain/state/state-native/v3/proofs.go b/beacon-chain/state/state-native/proofs.go similarity index 62% rename from beacon-chain/state/state-native/v3/proofs.go rename to beacon-chain/state/state-native/proofs.go index 3fa329408a..8bfb3a52d9 100644 --- a/beacon-chain/state/state-native/v3/proofs.go +++ b/beacon-chain/state/state-native/proofs.go @@ -1,11 +1,13 @@ -package v3 +package state_native import ( "context" "encoding/binary" "github.com/prysmaticlabs/prysm/beacon-chain/state/fieldtrie" + nativetypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/types" "github.com/prysmaticlabs/prysm/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/runtime/version" ) const ( @@ -18,19 +20,32 @@ func FinalizedRootGeneralizedIndex() uint64 { } // CurrentSyncCommitteeGeneralizedIndex for the beacon state. -func CurrentSyncCommitteeGeneralizedIndex() uint64 { - return uint64(currentSyncCommittee) +func (b *BeaconState) CurrentSyncCommitteeGeneralizedIndex() (uint64, error) { + if b.version == version.Phase0 { + return 0, errNotSupported("CurrentSyncCommitteeGeneralizedIndex", b.version) + } + + return uint64(nativetypes.CurrentSyncCommittee.RealPosition()), nil } // NextSyncCommitteeGeneralizedIndex for the beacon state. -func NextSyncCommitteeGeneralizedIndex() uint64 { - return uint64(nextSyncCommittee) +func (b *BeaconState) NextSyncCommitteeGeneralizedIndex() (uint64, error) { + if b.version == version.Phase0 { + return 0, errNotSupported("NextSyncCommitteeGeneralizedIndex", b.version) + } + + return uint64(nativetypes.NextSyncCommittee.RealPosition()), nil } // CurrentSyncCommitteeProof from the state's Merkle trie representation. func (b *BeaconState) CurrentSyncCommitteeProof(ctx context.Context) ([][]byte, error) { b.lock.Lock() defer b.lock.Unlock() + + if b.version == version.Phase0 { + return nil, errNotSupported("CurrentSyncCommitteeProof", b.version) + } + // In case the Merkle layers of the trie are not populated, we need // to perform some initialization. if err := b.initializeMerkleLayers(ctx); err != nil { @@ -41,20 +56,25 @@ func (b *BeaconState) CurrentSyncCommitteeProof(ctx context.Context) ([][]byte, if err := b.recomputeDirtyFields(ctx); err != nil { return nil, err } - return fieldtrie.ProofFromMerkleLayers(b.merkleLayers, currentSyncCommittee), nil + return fieldtrie.ProofFromMerkleLayers(b.merkleLayers, nativetypes.CurrentSyncCommittee.RealPosition()), nil } // NextSyncCommitteeProof from the state's Merkle trie representation. func (b *BeaconState) NextSyncCommitteeProof(ctx context.Context) ([][]byte, error) { b.lock.Lock() defer b.lock.Unlock() + + if b.version == version.Phase0 { + return nil, errNotSupported("NextSyncCommitteeProof", b.version) + } + if err := b.initializeMerkleLayers(ctx); err != nil { return nil, err } if err := b.recomputeDirtyFields(ctx); err != nil { return nil, err } - return fieldtrie.ProofFromMerkleLayers(b.merkleLayers, nextSyncCommittee), nil + return fieldtrie.ProofFromMerkleLayers(b.merkleLayers, nativetypes.NextSyncCommittee.RealPosition()), nil } // FinalizedRootProof crafts a Merkle proof for the finalized root @@ -62,13 +82,18 @@ func (b *BeaconState) NextSyncCommitteeProof(ctx context.Context) ([][]byte, err func (b *BeaconState) FinalizedRootProof(ctx context.Context) ([][]byte, error) { b.lock.Lock() defer b.lock.Unlock() + + if b.version == version.Phase0 { + return nil, errNotSupported("FinalizedRootProof", b.version) + } + if err := b.initializeMerkleLayers(ctx); err != nil { return nil, err } if err := b.recomputeDirtyFields(ctx); err != nil { return nil, err } - cpt := b.finalizedCheckpoint + cpt := b.finalizedCheckpointVal() // The epoch field of a finalized checkpoint is the neighbor // index of the finalized root field in its Merkle tree representation // of the checkpoint. This neighbor is the first element added to the proof. @@ -77,7 +102,7 @@ func (b *BeaconState) FinalizedRootProof(ctx context.Context) ([][]byte, error) epochRoot := bytesutil.ToBytes32(epochBuf) proof := make([][]byte, 0) proof = append(proof, epochRoot[:]) - branch := fieldtrie.ProofFromMerkleLayers(b.merkleLayers, finalizedCheckpoint) + branch := fieldtrie.ProofFromMerkleLayers(b.merkleLayers, nativetypes.FinalizedCheckpoint.RealPosition()) proof = append(proof, branch...) return proof, nil } diff --git a/beacon-chain/state/state-native/v1/proofs_test.go b/beacon-chain/state/state-native/proofs_test.go similarity index 90% rename from beacon-chain/state/state-native/v1/proofs_test.go rename to beacon-chain/state/state-native/proofs_test.go index f7778c44f6..468498f581 100644 --- a/beacon-chain/state/state-native/v1/proofs_test.go +++ b/beacon-chain/state/state-native/proofs_test.go @@ -1,10 +1,10 @@ -package v1_test +package state_native_test import ( "context" "testing" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/v1" + statenative "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native" "github.com/prysmaticlabs/prysm/container/trie" "github.com/prysmaticlabs/prysm/testing/require" "github.com/prysmaticlabs/prysm/testing/util" @@ -27,7 +27,7 @@ func TestBeaconStateMerkleProofs(t *testing.T) { finalizedRoot := st.FinalizedCheckpoint().Root proof, err := st.FinalizedRootProof(ctx) require.NoError(t, err) - gIndex := v1.FinalizedRootGeneralizedIndex() + gIndex := statenative.FinalizedRootGeneralizedIndex() valid := trie.VerifyMerkleProof(htr[:], finalizedRoot, gIndex, proof) require.Equal(t, true, valid) }) @@ -51,7 +51,7 @@ func TestBeaconStateMerkleProofs(t *testing.T) { // changed and should have been marked as a dirty state field. // The proof validity should be false for the old root, but true for the new. finalizedRoot := st.FinalizedCheckpoint().Root - gIndex := v1.FinalizedRootGeneralizedIndex() + gIndex := statenative.FinalizedRootGeneralizedIndex() valid := trie.VerifyMerkleProof(currentRoot[:], finalizedRoot, gIndex, proof) require.Equal(t, false, valid) diff --git a/beacon-chain/state/state-native/v1/readonly_validator.go b/beacon-chain/state/state-native/readonly_validator.go similarity index 99% rename from beacon-chain/state/state-native/v1/readonly_validator.go rename to beacon-chain/state/state-native/readonly_validator.go index 2168c635a4..b97cf22f91 100644 --- a/beacon-chain/state/state-native/v1/readonly_validator.go +++ b/beacon-chain/state/state-native/readonly_validator.go @@ -1,4 +1,4 @@ -package v1 +package state_native import ( "github.com/pkg/errors" diff --git a/beacon-chain/state/state-native/v1/readonly_validator_test.go b/beacon-chain/state/state-native/readonly_validator_test.go similarity index 64% rename from beacon-chain/state/state-native/v1/readonly_validator_test.go rename to beacon-chain/state/state-native/readonly_validator_test.go index f366c8b235..cabae98cfc 100644 --- a/beacon-chain/state/state-native/v1/readonly_validator_test.go +++ b/beacon-chain/state/state-native/readonly_validator_test.go @@ -1,9 +1,9 @@ -package v1_test +package state_native_test import ( "testing" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/v1" + statenative "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" types "github.com/prysmaticlabs/prysm/consensus-types/primitives" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" @@ -12,63 +12,63 @@ import ( ) func TestReadOnlyValidator_ReturnsErrorOnNil(t *testing.T) { - if _, err := v1.NewValidator(nil); err != v1.ErrNilWrappedValidator { - t.Errorf("Wrong error returned. Got %v, wanted %v", err, v1.ErrNilWrappedValidator) + if _, err := statenative.NewValidator(nil); err != statenative.ErrNilWrappedValidator { + t.Errorf("Wrong error returned. Got %v, wanted %v", err, statenative.ErrNilWrappedValidator) } } func TestReadOnlyValidator_EffectiveBalance(t *testing.T) { bal := uint64(234) - v, err := v1.NewValidator(ðpb.Validator{EffectiveBalance: bal}) + v, err := statenative.NewValidator(ðpb.Validator{EffectiveBalance: bal}) require.NoError(t, err) assert.Equal(t, bal, v.EffectiveBalance()) } func TestReadOnlyValidator_ActivationEligibilityEpoch(t *testing.T) { epoch := types.Epoch(234) - v, err := v1.NewValidator(ðpb.Validator{ActivationEligibilityEpoch: epoch}) + v, err := statenative.NewValidator(ðpb.Validator{ActivationEligibilityEpoch: epoch}) require.NoError(t, err) assert.Equal(t, epoch, v.ActivationEligibilityEpoch()) } func TestReadOnlyValidator_ActivationEpoch(t *testing.T) { epoch := types.Epoch(234) - v, err := v1.NewValidator(ðpb.Validator{ActivationEpoch: epoch}) + v, err := statenative.NewValidator(ðpb.Validator{ActivationEpoch: epoch}) require.NoError(t, err) assert.Equal(t, epoch, v.ActivationEpoch()) } func TestReadOnlyValidator_WithdrawableEpoch(t *testing.T) { epoch := types.Epoch(234) - v, err := v1.NewValidator(ðpb.Validator{WithdrawableEpoch: epoch}) + v, err := statenative.NewValidator(ðpb.Validator{WithdrawableEpoch: epoch}) require.NoError(t, err) assert.Equal(t, epoch, v.WithdrawableEpoch()) } func TestReadOnlyValidator_ExitEpoch(t *testing.T) { epoch := types.Epoch(234) - v, err := v1.NewValidator(ðpb.Validator{ExitEpoch: epoch}) + v, err := statenative.NewValidator(ðpb.Validator{ExitEpoch: epoch}) require.NoError(t, err) assert.Equal(t, epoch, v.ExitEpoch()) } func TestReadOnlyValidator_PublicKey(t *testing.T) { key := [fieldparams.BLSPubkeyLength]byte{0xFA, 0xCC} - v, err := v1.NewValidator(ðpb.Validator{PublicKey: key[:]}) + v, err := statenative.NewValidator(ðpb.Validator{PublicKey: key[:]}) require.NoError(t, err) assert.Equal(t, key, v.PublicKey()) } func TestReadOnlyValidator_WithdrawalCredentials(t *testing.T) { creds := []byte{0xFA, 0xCC} - v, err := v1.NewValidator(ðpb.Validator{WithdrawalCredentials: creds}) + v, err := statenative.NewValidator(ðpb.Validator{WithdrawalCredentials: creds}) require.NoError(t, err) assert.DeepEqual(t, creds, v.WithdrawalCredentials()) } func TestReadOnlyValidator_Slashed(t *testing.T) { slashed := true - v, err := v1.NewValidator(ðpb.Validator{Slashed: slashed}) + v, err := statenative.NewValidator(ðpb.Validator{Slashed: slashed}) require.NoError(t, err) assert.Equal(t, slashed, v.Slashed()) } diff --git a/beacon-chain/state/state-native/references_test.go b/beacon-chain/state/state-native/references_test.go new file mode 100644 index 0000000000..0b6e4df030 --- /dev/null +++ b/beacon-chain/state/state-native/references_test.go @@ -0,0 +1,715 @@ +package state_native + +import ( + "reflect" + "runtime" + "runtime/debug" + "testing" + + "github.com/prysmaticlabs/go-bitfield" + "github.com/prysmaticlabs/prysm/beacon-chain/state" + nativetypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/types" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/testing/assert" + "github.com/prysmaticlabs/prysm/testing/require" +) + +func TestStateReferenceSharing_Finalizer_Phase0(t *testing.T) { + // This test showcases the logic on the RandaoMixes field with the GC finalizer. + + s, err := InitializeFromProtoUnsafePhase0(ðpb.BeaconState{RandaoMixes: [][]byte{[]byte("foo")}}) + require.NoError(t, err) + a, ok := s.(*BeaconState) + require.Equal(t, true, ok) + assert.Equal(t, uint(1), a.sharedFieldReferences[nativetypes.RandaoMixes].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[nativetypes.RandaoMixes].Refs(), "Expected 2 references to RANDAO mixes") + _ = b + }() + + runtime.GC() // Should run finalizer on object b + assert.Equal(t, uint(1), a.sharedFieldReferences[nativetypes.RandaoMixes].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[nativetypes.RandaoMixes].Refs(), "Expected 2 shared references to RANDAO mixes") + require.NoError(t, b.UpdateRandaoMixesAtIndex(0, []byte("bar"))) + if b.sharedFieldReferences[nativetypes.RandaoMixes].Refs() != 1 || a.sharedFieldReferences[nativetypes.RandaoMixes].Refs() != 1 { + t.Error("Expected 1 shared reference to RANDAO mix 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. + + s, err := InitializeFromProtoUnsafeAltair(ðpb.BeaconStateAltair{RandaoMixes: [][]byte{[]byte("foo")}}) + require.NoError(t, err) + a, ok := s.(*BeaconState) + require.Equal(t, true, ok) + assert.Equal(t, uint(1), a.sharedFieldReferences[nativetypes.RandaoMixes].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[nativetypes.RandaoMixes].Refs(), "Expected 2 references to RANDAO mixes") + _ = b + }() + + runtime.GC() // Should run finalizer on object b + assert.Equal(t, uint(1), a.sharedFieldReferences[nativetypes.RandaoMixes].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[nativetypes.RandaoMixes].Refs(), "Expected 2 shared references to RANDAO mixes") + require.NoError(t, b.UpdateRandaoMixesAtIndex(0, []byte("bar"))) + if b.sharedFieldReferences[nativetypes.RandaoMixes].Refs() != 1 || a.sharedFieldReferences[nativetypes.RandaoMixes].Refs() != 1 { + t.Error("Expected 1 shared reference to RANDAO mix 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. + + s, err := InitializeFromProtoUnsafeBellatrix(ðpb.BeaconStateBellatrix{RandaoMixes: [][]byte{[]byte("foo")}}) + require.NoError(t, err) + a, ok := s.(*BeaconState) + require.Equal(t, true, ok) + assert.Equal(t, uint(1), a.sharedFieldReferences[nativetypes.RandaoMixes].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[nativetypes.RandaoMixes].Refs(), "Expected 2 references to RANDAO mixes") + _ = b + }() + + runtime.GC() // Should run finalizer on object b + assert.Equal(t, uint(1), a.sharedFieldReferences[nativetypes.RandaoMixes].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[nativetypes.RandaoMixes].Refs(), "Expected 2 shared references to RANDAO mixes") + require.NoError(t, b.UpdateRandaoMixesAtIndex(0, []byte("bar"))) + if b.sharedFieldReferences[nativetypes.RandaoMixes].Refs() != 1 || a.sharedFieldReferences[nativetypes.RandaoMixes].Refs() != 1 { + t.Error("Expected 1 shared reference to RANDAO mix for both a and b") + } +} + +func TestStateReferenceCopy_NoUnexpectedRootsMutation_Phase0(t *testing.T) { + root1, root2 := bytesutil.ToBytes32([]byte("foo")), bytesutil.ToBytes32([]byte("bar")) + s, err := InitializeFromProtoUnsafePhase0(ðpb.BeaconState{ + BlockRoots: [][]byte{ + root1[:], + }, + StateRoots: [][]byte{ + root1[:], + }, + }) + require.NoError(t, err) + a, ok := s.(*BeaconState) + require.Equal(t, true, ok) + require.NoError(t, err) + assertRefCount(t, a, nativetypes.BlockRoots, 1) + assertRefCount(t, a, nativetypes.StateRoots, 1) + + // Copy, increases reference count. + copied := a.Copy() + b, ok := copied.(*BeaconState) + require.Equal(t, true, ok) + assertRefCount(t, a, nativetypes.BlockRoots, 2) + assertRefCount(t, a, nativetypes.StateRoots, 2) + assertRefCount(t, b, nativetypes.BlockRoots, 2) + assertRefCount(t, b, nativetypes.StateRoots, 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[:]) + + // Mutator should only affect calling state: a. + require.NoError(t, a.UpdateBlockRootAtIndex(0, root2)) + require.NoError(t, a.UpdateStateRootAtIndex(0, root2)) + + // 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") + + // Copy on write happened, reference counters are reset. + assertRefCount(t, a, nativetypes.BlockRoots, 1) + assertRefCount(t, a, nativetypes.StateRoots, 1) + assertRefCount(t, b, nativetypes.BlockRoots, 1) + assertRefCount(t, b, nativetypes.StateRoots, 1) +} + +func TestStateReferenceCopy_NoUnexpectedRootsMutation_Altair(t *testing.T) { + root1, root2 := bytesutil.ToBytes32([]byte("foo")), bytesutil.ToBytes32([]byte("bar")) + s, err := InitializeFromProtoUnsafeAltair(ðpb.BeaconStateAltair{ + BlockRoots: [][]byte{ + root1[:], + }, + StateRoots: [][]byte{ + root1[:], + }, + }) + require.NoError(t, err) + a, ok := s.(*BeaconState) + require.Equal(t, true, ok) + require.NoError(t, err) + assertRefCount(t, a, nativetypes.BlockRoots, 1) + assertRefCount(t, a, nativetypes.StateRoots, 1) + + // Copy, increases reference count. + copied := a.Copy() + b, ok := copied.(*BeaconState) + require.Equal(t, true, ok) + assertRefCount(t, a, nativetypes.BlockRoots, 2) + assertRefCount(t, a, nativetypes.StateRoots, 2) + assertRefCount(t, b, nativetypes.BlockRoots, 2) + assertRefCount(t, b, nativetypes.StateRoots, 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[:]) + + // Mutator should only affect calling state: a. + require.NoError(t, a.UpdateBlockRootAtIndex(0, root2)) + require.NoError(t, a.UpdateStateRootAtIndex(0, root2)) + + // 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") + + // Copy on write happened, reference counters are reset. + assertRefCount(t, a, nativetypes.BlockRoots, 1) + assertRefCount(t, a, nativetypes.StateRoots, 1) + assertRefCount(t, b, nativetypes.BlockRoots, 1) + assertRefCount(t, b, nativetypes.StateRoots, 1) +} + +func TestStateReferenceCopy_NoUnexpectedRootsMutation_Bellatrix(t *testing.T) { + root1, root2 := bytesutil.ToBytes32([]byte("foo")), bytesutil.ToBytes32([]byte("bar")) + s, err := InitializeFromProtoUnsafeBellatrix(ðpb.BeaconStateBellatrix{ + BlockRoots: [][]byte{ + root1[:], + }, + StateRoots: [][]byte{ + root1[:], + }, + }) + require.NoError(t, err) + a, ok := s.(*BeaconState) + require.Equal(t, true, ok) + require.NoError(t, err) + assertRefCount(t, a, nativetypes.BlockRoots, 1) + assertRefCount(t, a, nativetypes.StateRoots, 1) + + // Copy, increases reference count. + copied := a.Copy() + b, ok := copied.(*BeaconState) + require.Equal(t, true, ok) + assertRefCount(t, a, nativetypes.BlockRoots, 2) + assertRefCount(t, a, nativetypes.StateRoots, 2) + assertRefCount(t, b, nativetypes.BlockRoots, 2) + assertRefCount(t, b, nativetypes.StateRoots, 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[:]) + + // Mutator should only affect calling state: a. + require.NoError(t, a.UpdateBlockRootAtIndex(0, root2)) + require.NoError(t, a.UpdateStateRootAtIndex(0, root2)) + + // 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") + + // Copy on write happened, reference counters are reset. + assertRefCount(t, a, nativetypes.BlockRoots, 1) + assertRefCount(t, a, nativetypes.StateRoots, 1) + assertRefCount(t, b, nativetypes.BlockRoots, 1) + assertRefCount(t, b, nativetypes.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, nativetypes.RandaoMixes, 1) + + // Copy, increases reference count. + copied := a.Copy() + b, ok := copied.(*BeaconState) + require.Equal(t, true, ok) + assertRefCount(t, a, nativetypes.RandaoMixes, 2) + assertRefCount(t, b, nativetypes.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, nativetypes.RandaoMixes, 1) + assertRefCount(t, b, nativetypes.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, nativetypes.RandaoMixes, 1) + + // Copy, increases reference count. + copied := a.Copy() + b, ok := copied.(*BeaconState) + require.Equal(t, true, ok) + assertRefCount(t, a, nativetypes.RandaoMixes, 2) + assertRefCount(t, b, nativetypes.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, nativetypes.RandaoMixes, 1) + assertRefCount(t, b, nativetypes.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, nativetypes.RandaoMixes, 1) + + // Copy, increases reference count. + copied := a.Copy() + b, ok := copied.(*BeaconState) + require.Equal(t, true, ok) + assertRefCount(t, a, nativetypes.RandaoMixes, 2) + assertRefCount(t, b, nativetypes.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, nativetypes.RandaoMixes, 1) + assertRefCount(t, b, nativetypes.RandaoMixes, 1) +} + +func TestStateReferenceCopy_NoUnexpectedAttestationsMutation(t *testing.T) { + assertAttFound := func(vals []*ethpb.PendingAttestation, val uint64) { + for i := range vals { + if reflect.DeepEqual(vals[i].AggregationBits, bitfield.NewBitlist(val)) { + return + } + } + t.Log(string(debug.Stack())) + t.Fatalf("Expected attestation not found (%v), want: %v", vals, val) + } + assertAttNotFound := func(vals []*ethpb.PendingAttestation, val uint64) { + for i := range vals { + if reflect.DeepEqual(vals[i].AggregationBits, bitfield.NewBitlist(val)) { + t.Log(string(debug.Stack())) + t.Fatalf("Unexpected attestation found (%v): %v", vals, val) + return + } + } + } + + s, err := InitializeFromProtoUnsafePhase0(ðpb.BeaconState{}) + require.NoError(t, err) + a, ok := s.(*BeaconState) + require.Equal(t, true, ok) + assertRefCount(t, a, nativetypes.PreviousEpochAttestations, 1) + assertRefCount(t, a, nativetypes.CurrentEpochAttestations, 1) + + // Update initial state. + atts := []*ethpb.PendingAttestation{ + {AggregationBits: bitfield.NewBitlist(1)}, + {AggregationBits: bitfield.NewBitlist(2)}, + } + a.setPreviousEpochAttestations(atts[:1]) + a.setCurrentEpochAttestations(atts[:1]) + curAtt, err := a.CurrentEpochAttestations() + require.NoError(t, err) + assert.Equal(t, 1, len(curAtt), "Unexpected number of attestations") + preAtt, err := a.PreviousEpochAttestations() + require.NoError(t, err) + assert.Equal(t, 1, len(preAtt), "Unexpected number of attestations") + + // Copy, increases reference count. + copied := a.Copy() + b, ok := copied.(*BeaconState) + require.Equal(t, true, ok) + assertRefCount(t, a, nativetypes.PreviousEpochAttestations, 2) + assertRefCount(t, a, nativetypes.CurrentEpochAttestations, 2) + assertRefCount(t, b, nativetypes.PreviousEpochAttestations, 2) + assertRefCount(t, b, nativetypes.CurrentEpochAttestations, 2) + prevAtts, err := b.PreviousEpochAttestations() + require.NoError(t, err) + assert.Equal(t, 1, len(prevAtts), "Unexpected number of attestations") + currAtts, err := b.CurrentEpochAttestations() + require.NoError(t, err) + assert.Equal(t, 1, len(currAtts), "Unexpected number of attestations") + + // Assert shared state. + currAttsA, err := a.CurrentEpochAttestations() + require.NoError(t, err) + prevAttsA, err := a.PreviousEpochAttestations() + require.NoError(t, err) + currAttsB, err := b.CurrentEpochAttestations() + require.NoError(t, err) + prevAttsB, err := b.PreviousEpochAttestations() + require.NoError(t, err) + if len(currAttsA) != len(currAttsB) || len(currAttsA) < 1 { + t.Errorf("Unexpected number of attestations, want: %v", 1) + } + if len(prevAttsA) != len(prevAttsB) || len(prevAttsA) < 1 { + t.Errorf("Unexpected number of attestations, want: %v", 1) + } + assertAttFound(currAttsA, 1) + assertAttFound(prevAttsA, 1) + assertAttFound(currAttsB, 1) + assertAttFound(prevAttsB, 1) + + // Extend state attestations. + require.NoError(t, a.AppendCurrentEpochAttestations(atts[1])) + require.NoError(t, a.AppendPreviousEpochAttestations(atts[1])) + curAtt, err = a.CurrentEpochAttestations() + require.NoError(t, err) + assert.Equal(t, 2, len(curAtt), "Unexpected number of attestations") + preAtt, err = a.PreviousEpochAttestations() + require.NoError(t, err) + assert.Equal(t, 2, len(preAtt), "Unexpected number of attestations") + currAttsA, err = a.CurrentEpochAttestations() + require.NoError(t, err) + prevAttsA, err = a.PreviousEpochAttestations() + require.NoError(t, err) + currAttsB, err = b.CurrentEpochAttestations() + require.NoError(t, err) + prevAttsB, err = b.PreviousEpochAttestations() + require.NoError(t, err) + assertAttFound(currAttsA, 1) + assertAttFound(prevAttsA, 1) + assertAttFound(currAttsA, 2) + assertAttFound(prevAttsA, 2) + assertAttFound(currAttsB, 1) + assertAttFound(prevAttsB, 1) + assertAttNotFound(currAttsB, 2) + assertAttNotFound(prevAttsB, 2) + + // Mutator should only affect calling state: a. + applyToEveryAttestation := func(state *BeaconState) { + // One MUST copy on write. + currEpochAtts, err := state.CurrentEpochAttestations() + require.NoError(t, err) + atts = make([]*ethpb.PendingAttestation, len(currEpochAtts)) + copy(atts, currEpochAtts) + state.setCurrentEpochAttestations(atts) + currEpochAtts, err = state.CurrentEpochAttestations() + require.NoError(t, err) + for i := range currEpochAtts { + att := ethpb.CopyPendingAttestation(currEpochAtts[i]) + att.AggregationBits = bitfield.NewBitlist(3) + currEpochAtts[i] = att + } + state.setCurrentEpochAttestations(currEpochAtts) + + prevEpochAtts, err := state.PreviousEpochAttestations() + require.NoError(t, err) + atts = make([]*ethpb.PendingAttestation, len(prevEpochAtts)) + copy(atts, prevEpochAtts) + state.setPreviousEpochAttestations(atts) + prevEpochAtts, err = state.PreviousEpochAttestations() + require.NoError(t, err) + for i := range prevEpochAtts { + att := ethpb.CopyPendingAttestation(prevEpochAtts[i]) + att.AggregationBits = bitfield.NewBitlist(3) + prevEpochAtts[i] = att + } + state.setPreviousEpochAttestations(prevEpochAtts) + } + applyToEveryAttestation(a) + + // Assert no shared state mutation occurred only on state a (copy on write). + currAttsA, err = a.CurrentEpochAttestations() + require.NoError(t, err) + prevAttsA, err = a.PreviousEpochAttestations() + require.NoError(t, err) + assertAttFound(currAttsA, 3) + assertAttFound(prevAttsA, 3) + assertAttNotFound(currAttsA, 1) + assertAttNotFound(prevAttsA, 1) + assertAttNotFound(currAttsA, 2) + assertAttNotFound(prevAttsA, 2) + // State b must be unaffected. + currAttsB, err = b.CurrentEpochAttestations() + require.NoError(t, err) + prevAttsB, err = b.PreviousEpochAttestations() + require.NoError(t, err) + assertAttNotFound(currAttsB, 3) + assertAttNotFound(prevAttsB, 3) + assertAttFound(currAttsB, 1) + assertAttFound(prevAttsB, 1) + assertAttNotFound(currAttsB, 2) + assertAttNotFound(prevAttsB, 2) + + // Copy on write happened, reference counters are reset. + assertRefCount(t, a, nativetypes.CurrentEpochAttestations, 1) + assertRefCount(t, b, nativetypes.CurrentEpochAttestations, 1) + assertRefCount(t, a, nativetypes.PreviousEpochAttestations, 1) + assertRefCount(t, b, nativetypes.PreviousEpochAttestations, 1) +} + +func TestValidatorReferences_RemainsConsistent_Phase0(t *testing.T) { + s, err := InitializeFromProtoUnsafePhase0(ðpb.BeaconState{ + Validators: []*ethpb.Validator{ + {PublicKey: []byte{'A'}}, + {PublicKey: []byte{'B'}}, + {PublicKey: []byte{'C'}}, + {PublicKey: []byte{'D'}}, + {PublicKey: []byte{'E'}}, + }, + }) + require.NoError(t, err) + a, ok := s.(*BeaconState) + require.Equal(t, true, ok) + + // Create a second state. + copied := a.Copy() + b, ok := copied.(*BeaconState) + require.Equal(t, true, ok) + + // Update First Validator. + assert.NoError(t, a.UpdateValidatorAtIndex(0, ðpb.Validator{PublicKey: []byte{'Z'}})) + + assert.DeepNotEqual(t, a.Validators()[0], b.Validators()[0], "validators are equal when they are supposed to be different") + // Modify all validators from copied state. + assert.NoError(t, b.ApplyToEveryValidator(func(idx int, val *ethpb.Validator) (bool, *ethpb.Validator, error) { + return true, ðpb.Validator{PublicKey: []byte{'V'}}, nil + })) + + // Ensure reference is properly accounted for. + assert.NoError(t, a.ReadFromEveryValidator(func(idx int, val state.ReadOnlyValidator) error { + assert.NotEqual(t, bytesutil.ToBytes48([]byte{'V'}), val.PublicKey()) + return nil + })) +} + +func TestValidatorReferences_RemainsConsistent_Altair(t *testing.T) { + s, err := InitializeFromProtoUnsafeAltair(ðpb.BeaconStateAltair{ + Validators: []*ethpb.Validator{ + {PublicKey: []byte{'A'}}, + {PublicKey: []byte{'B'}}, + {PublicKey: []byte{'C'}}, + {PublicKey: []byte{'D'}}, + {PublicKey: []byte{'E'}}, + }, + }) + require.NoError(t, err) + a, ok := s.(*BeaconState) + require.Equal(t, true, ok) + + // Create a second state. + copied := a.Copy() + b, ok := copied.(*BeaconState) + require.Equal(t, true, ok) + + // Update First Validator. + assert.NoError(t, a.UpdateValidatorAtIndex(0, ðpb.Validator{PublicKey: []byte{'Z'}})) + + assert.DeepNotEqual(t, a.Validators()[0], b.Validators()[0], "validators are equal when they are supposed to be different") + // Modify all validators from copied state. + assert.NoError(t, b.ApplyToEveryValidator(func(idx int, val *ethpb.Validator) (bool, *ethpb.Validator, error) { + return true, ðpb.Validator{PublicKey: []byte{'V'}}, nil + })) + + // Ensure reference is properly accounted for. + assert.NoError(t, a.ReadFromEveryValidator(func(idx int, val state.ReadOnlyValidator) error { + assert.NotEqual(t, bytesutil.ToBytes48([]byte{'V'}), val.PublicKey()) + return nil + })) +} + +func TestValidatorReferences_RemainsConsistent_Bellatrix(t *testing.T) { + s, err := InitializeFromProtoUnsafeBellatrix(ðpb.BeaconStateBellatrix{ + Validators: []*ethpb.Validator{ + {PublicKey: []byte{'A'}}, + {PublicKey: []byte{'B'}}, + {PublicKey: []byte{'C'}}, + {PublicKey: []byte{'D'}}, + {PublicKey: []byte{'E'}}, + }, + }) + require.NoError(t, err) + a, ok := s.(*BeaconState) + require.Equal(t, true, ok) + + // Create a second state. + copied := a.Copy() + b, ok := copied.(*BeaconState) + require.Equal(t, true, ok) + + // Update First Validator. + assert.NoError(t, a.UpdateValidatorAtIndex(0, ðpb.Validator{PublicKey: []byte{'Z'}})) + + assert.DeepNotEqual(t, a.Validators()[0], b.Validators()[0], "validators are equal when they are supposed to be different") + // Modify all validators from copied state. + assert.NoError(t, b.ApplyToEveryValidator(func(idx int, val *ethpb.Validator) (bool, *ethpb.Validator, error) { + return true, ðpb.Validator{PublicKey: []byte{'V'}}, nil + })) + + // Ensure reference is properly accounted for. + assert.NoError(t, a.ReadFromEveryValidator(func(idx int, val state.ReadOnlyValidator) error { + assert.NotEqual(t, bytesutil.ToBytes48([]byte{'V'}), val.PublicKey()) + return nil + })) +} + +// assertRefCount checks whether reference count for a given state +// at a given index is equal to expected amount. +func assertRefCount(t *testing.T, b *BeaconState, idx nativetypes.FieldIndex, want uint) { + if cnt := b.sharedFieldReferences[idx].Refs(); cnt != want { + t.Errorf("Unexpected count of references for index %d, want: %v, got: %v", idx, want, cnt) + } +} + +// assertValFound checks whether item with a given value exists in list. +func assertValFound(t *testing.T, vals [][]byte, val []byte) { + for i := range vals { + if reflect.DeepEqual(vals[i], val) { + return + } + } + t.Log(string(debug.Stack())) + t.Fatalf("Expected value not found (%v), want: %v", vals, val) +} + +// assertValNotFound checks whether item with a given value doesn't exist in list. +func assertValNotFound(t *testing.T, vals [][]byte, val []byte) { + for i := range vals { + if reflect.DeepEqual(vals[i], val) { + t.Log(string(debug.Stack())) + t.Errorf("Unexpected value found (%v),: %v", vals, val) + return + } + } +} diff --git a/beacon-chain/state/state-native/v1/setters_attestation.go b/beacon-chain/state/state-native/setters_attestation.go similarity index 53% rename from beacon-chain/state/state-native/v1/setters_attestation.go rename to beacon-chain/state/state-native/setters_attestation.go index 45d36b7167..3a360babbc 100644 --- a/beacon-chain/state/state-native/v1/setters_attestation.go +++ b/beacon-chain/state/state-native/setters_attestation.go @@ -1,11 +1,13 @@ -package v1 +package state_native import ( "fmt" + nativetypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/types" "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/runtime/version" ) // RotateAttestations sets the previous epoch attestations to the current epoch attestations and @@ -14,27 +16,31 @@ func (b *BeaconState) RotateAttestations() error { b.lock.Lock() defer b.lock.Unlock() + if b.version != version.Phase0 { + return errNotSupported("RotateAttestations", b.version) + } + b.setPreviousEpochAttestations(b.currentEpochAttestationsVal()) b.setCurrentEpochAttestations([]*ethpb.PendingAttestation{}) return nil } func (b *BeaconState) setPreviousEpochAttestations(val []*ethpb.PendingAttestation) { - b.sharedFieldReferences[previousEpochAttestations].MinusRef() - b.sharedFieldReferences[previousEpochAttestations] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.PreviousEpochAttestations].MinusRef() + b.sharedFieldReferences[nativetypes.PreviousEpochAttestations] = stateutil.NewRef(1) b.previousEpochAttestations = val - b.markFieldAsDirty(previousEpochAttestations) - b.rebuildTrie[previousEpochAttestations] = true + b.markFieldAsDirty(nativetypes.PreviousEpochAttestations) + b.rebuildTrie[nativetypes.PreviousEpochAttestations] = true } func (b *BeaconState) setCurrentEpochAttestations(val []*ethpb.PendingAttestation) { - b.sharedFieldReferences[currentEpochAttestations].MinusRef() - b.sharedFieldReferences[currentEpochAttestations] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.CurrentEpochAttestations].MinusRef() + b.sharedFieldReferences[nativetypes.CurrentEpochAttestations] = stateutil.NewRef(1) b.currentEpochAttestations = val - b.markFieldAsDirty(currentEpochAttestations) - b.rebuildTrie[currentEpochAttestations] = true + b.markFieldAsDirty(nativetypes.CurrentEpochAttestations) + b.rebuildTrie[nativetypes.CurrentEpochAttestations] = true } // AppendCurrentEpochAttestations for the beacon state. Appends the new value @@ -43,23 +49,27 @@ func (b *BeaconState) AppendCurrentEpochAttestations(val *ethpb.PendingAttestati b.lock.Lock() defer b.lock.Unlock() + if b.version != version.Phase0 { + return errNotSupported("AppendCurrentEpochAttestations", b.version) + } + atts := b.currentEpochAttestations max := uint64(fieldparams.CurrentEpochAttestationsLength) if uint64(len(atts)) >= max { return fmt.Errorf("current pending attestation exceeds max length %d", max) } - if b.sharedFieldReferences[currentEpochAttestations].Refs() > 1 { + if b.sharedFieldReferences[nativetypes.CurrentEpochAttestations].Refs() > 1 { // Copy elements in underlying array by reference. atts = make([]*ethpb.PendingAttestation, len(b.currentEpochAttestations)) copy(atts, b.currentEpochAttestations) - b.sharedFieldReferences[currentEpochAttestations].MinusRef() - b.sharedFieldReferences[currentEpochAttestations] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.CurrentEpochAttestations].MinusRef() + b.sharedFieldReferences[nativetypes.CurrentEpochAttestations] = stateutil.NewRef(1) } b.currentEpochAttestations = append(atts, val) - b.markFieldAsDirty(currentEpochAttestations) - b.addDirtyIndices(currentEpochAttestations, []uint64{uint64(len(b.currentEpochAttestations) - 1)}) + b.markFieldAsDirty(nativetypes.CurrentEpochAttestations) + b.addDirtyIndices(nativetypes.CurrentEpochAttestations, []uint64{uint64(len(b.currentEpochAttestations) - 1)}) return nil } @@ -69,21 +79,25 @@ func (b *BeaconState) AppendPreviousEpochAttestations(val *ethpb.PendingAttestat b.lock.Lock() defer b.lock.Unlock() + if b.version != version.Phase0 { + return errNotSupported("AppendPreviousEpochAttestations", b.version) + } + atts := b.previousEpochAttestations max := uint64(fieldparams.PreviousEpochAttestationsLength) if uint64(len(atts)) >= max { return fmt.Errorf("previous pending attestation exceeds max length %d", max) } - if b.sharedFieldReferences[previousEpochAttestations].Refs() > 1 { + if b.sharedFieldReferences[nativetypes.PreviousEpochAttestations].Refs() > 1 { atts = make([]*ethpb.PendingAttestation, len(b.previousEpochAttestations)) copy(atts, b.previousEpochAttestations) - b.sharedFieldReferences[previousEpochAttestations].MinusRef() - b.sharedFieldReferences[previousEpochAttestations] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.PreviousEpochAttestations].MinusRef() + b.sharedFieldReferences[nativetypes.PreviousEpochAttestations] = stateutil.NewRef(1) } b.previousEpochAttestations = append(atts, val) - b.markFieldAsDirty(previousEpochAttestations) - b.addDirtyIndices(previousEpochAttestations, []uint64{uint64(len(b.previousEpochAttestations) - 1)}) + b.markFieldAsDirty(nativetypes.PreviousEpochAttestations) + b.addDirtyIndices(nativetypes.PreviousEpochAttestations, []uint64{uint64(len(b.previousEpochAttestations) - 1)}) return nil } diff --git a/beacon-chain/state/state-native/v1/setters_attestation_test.go b/beacon-chain/state/state-native/setters_attestation_test.go similarity index 63% rename from beacon-chain/state/state-native/v1/setters_attestation_test.go rename to beacon-chain/state/state-native/setters_attestation_test.go index fde2fd2e5e..81d5f887ee 100644 --- a/beacon-chain/state/state-native/v1/setters_attestation_test.go +++ b/beacon-chain/state/state-native/setters_attestation_test.go @@ -1,4 +1,4 @@ -package v1 +package state_native import ( "testing" @@ -9,7 +9,7 @@ import ( ) func TestBeaconState_RotateAttestations(t *testing.T) { - st, err := InitializeFromProto(ðpb.BeaconState{ + st, err := InitializeFromProtoPhase0(ðpb.BeaconState{ Slot: 1, CurrentEpochAttestations: []*ethpb.PendingAttestation{{Data: ðpb.AttestationData{Slot: 456}}}, PreviousEpochAttestations: []*ethpb.PendingAttestation{{Data: ðpb.AttestationData{Slot: 123}}}, @@ -17,10 +17,8 @@ func TestBeaconState_RotateAttestations(t *testing.T) { require.NoError(t, err) require.NoError(t, st.RotateAttestations()) - currEpochAtts, err := st.CurrentEpochAttestations() - require.NoError(t, err) - require.Equal(t, 0, len(currEpochAtts)) - prevEpochAtts, err := st.PreviousEpochAttestations() - require.NoError(t, err) - require.Equal(t, types.Slot(456), prevEpochAtts[0].Data.Slot) + s, ok := st.(*BeaconState) + require.Equal(t, true, ok) + require.Equal(t, 0, len(s.currentEpochAttestationsVal())) + require.Equal(t, types.Slot(456), s.previousEpochAttestationsVal()[0].Data.Slot) } diff --git a/beacon-chain/state/state-native/v1/setters_block.go b/beacon-chain/state/state-native/setters_block.go similarity index 70% rename from beacon-chain/state/state-native/v1/setters_block.go rename to beacon-chain/state/state-native/setters_block.go index f76c2b7825..9750728588 100644 --- a/beacon-chain/state/state-native/v1/setters_block.go +++ b/beacon-chain/state/state-native/setters_block.go @@ -1,9 +1,10 @@ -package v1 +package state_native import ( "fmt" customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types" + nativetypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/types" "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" @@ -15,7 +16,7 @@ func (b *BeaconState) SetLatestBlockHeader(val *ethpb.BeaconBlockHeader) error { defer b.lock.Unlock() b.latestBlockHeader = ethpb.CopyBeaconBlockHeader(val) - b.markFieldAsDirty(latestBlockHeader) + b.markFieldAsDirty(nativetypes.LatestBlockHeader) return nil } @@ -25,8 +26,8 @@ func (b *BeaconState) SetBlockRoots(val [][]byte) error { b.lock.Lock() defer b.lock.Unlock() - b.sharedFieldReferences[blockRoots].MinusRef() - b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.BlockRoots].MinusRef() + b.sharedFieldReferences[nativetypes.BlockRoots] = stateutil.NewRef(1) var rootsArr [fieldparams.BlockRootsLength][32]byte for i := 0; i < len(rootsArr); i++ { @@ -34,8 +35,8 @@ func (b *BeaconState) SetBlockRoots(val [][]byte) error { } roots := customtypes.BlockRoots(rootsArr) b.blockRoots = &roots - b.markFieldAsDirty(blockRoots) - b.rebuildTrie[blockRoots] = true + b.markFieldAsDirty(nativetypes.BlockRoots) + b.rebuildTrie[nativetypes.BlockRoots] = true return nil } @@ -49,19 +50,19 @@ func (b *BeaconState) UpdateBlockRootAtIndex(idx uint64, blockRoot [32]byte) err defer b.lock.Unlock() r := b.blockRoots - if ref := b.sharedFieldReferences[blockRoots]; ref.Refs() > 1 { + if ref := b.sharedFieldReferences[nativetypes.BlockRoots]; ref.Refs() > 1 { // Copy elements in underlying array by reference. roots := *b.blockRoots rootsCopy := roots r = &rootsCopy ref.MinusRef() - b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.BlockRoots] = stateutil.NewRef(1) } r[idx] = blockRoot b.blockRoots = r - b.markFieldAsDirty(blockRoots) - b.addDirtyIndices(blockRoots, []uint64{idx}) + b.markFieldAsDirty(nativetypes.BlockRoots) + b.addDirtyIndices(nativetypes.BlockRoots, []uint64{idx}) return nil } diff --git a/beacon-chain/state/state-native/v2/setters_checkpoint.go b/beacon-chain/state/state-native/setters_checkpoint.go similarity index 74% rename from beacon-chain/state/state-native/v2/setters_checkpoint.go rename to beacon-chain/state/state-native/setters_checkpoint.go index a95a8d66be..84ee7e6773 100644 --- a/beacon-chain/state/state-native/v2/setters_checkpoint.go +++ b/beacon-chain/state/state-native/setters_checkpoint.go @@ -1,7 +1,8 @@ -package v2 +package state_native import ( "github.com/prysmaticlabs/go-bitfield" + nativetypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/types" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ) @@ -11,7 +12,7 @@ func (b *BeaconState) SetJustificationBits(val bitfield.Bitvector4) error { defer b.lock.Unlock() b.justificationBits = val - b.markFieldAsDirty(justificationBits) + b.markFieldAsDirty(nativetypes.JustificationBits) return nil } @@ -21,7 +22,7 @@ func (b *BeaconState) SetPreviousJustifiedCheckpoint(val *ethpb.Checkpoint) erro defer b.lock.Unlock() b.previousJustifiedCheckpoint = val - b.markFieldAsDirty(previousJustifiedCheckpoint) + b.markFieldAsDirty(nativetypes.PreviousJustifiedCheckpoint) return nil } @@ -31,7 +32,7 @@ func (b *BeaconState) SetCurrentJustifiedCheckpoint(val *ethpb.Checkpoint) error defer b.lock.Unlock() b.currentJustifiedCheckpoint = val - b.markFieldAsDirty(currentJustifiedCheckpoint) + b.markFieldAsDirty(nativetypes.CurrentJustifiedCheckpoint) return nil } @@ -41,6 +42,6 @@ func (b *BeaconState) SetFinalizedCheckpoint(val *ethpb.Checkpoint) error { defer b.lock.Unlock() b.finalizedCheckpoint = val - b.markFieldAsDirty(finalizedCheckpoint) + b.markFieldAsDirty(nativetypes.FinalizedCheckpoint) return nil } diff --git a/beacon-chain/state/state-native/v3/setters_eth1.go b/beacon-chain/state/state-native/setters_eth1.go similarity index 60% rename from beacon-chain/state/state-native/v3/setters_eth1.go rename to beacon-chain/state/state-native/setters_eth1.go index 4167599ef7..7e0af8fa45 100644 --- a/beacon-chain/state/state-native/v3/setters_eth1.go +++ b/beacon-chain/state/state-native/setters_eth1.go @@ -1,6 +1,7 @@ -package v3 +package state_native import ( + nativetypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/types" "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ) @@ -11,7 +12,7 @@ func (b *BeaconState) SetEth1Data(val *ethpb.Eth1Data) error { defer b.lock.Unlock() b.eth1Data = val - b.markFieldAsDirty(eth1Data) + b.markFieldAsDirty(nativetypes.Eth1Data) return nil } @@ -21,12 +22,12 @@ func (b *BeaconState) SetEth1DataVotes(val []*ethpb.Eth1Data) error { b.lock.Lock() defer b.lock.Unlock() - b.sharedFieldReferences[eth1DataVotes].MinusRef() - b.sharedFieldReferences[eth1DataVotes] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.Eth1DataVotes].MinusRef() + b.sharedFieldReferences[nativetypes.Eth1DataVotes] = stateutil.NewRef(1) b.eth1DataVotes = val - b.markFieldAsDirty(eth1DataVotes) - b.rebuildTrie[eth1DataVotes] = true + b.markFieldAsDirty(nativetypes.Eth1DataVotes) + b.rebuildTrie[nativetypes.Eth1DataVotes] = true return nil } @@ -36,7 +37,7 @@ func (b *BeaconState) SetEth1DepositIndex(val uint64) error { defer b.lock.Unlock() b.eth1DepositIndex = val - b.markFieldAsDirty(eth1DepositIndex) + b.markFieldAsDirty(nativetypes.Eth1DepositIndex) return nil } @@ -47,16 +48,16 @@ func (b *BeaconState) AppendEth1DataVotes(val *ethpb.Eth1Data) error { defer b.lock.Unlock() votes := b.eth1DataVotes - if b.sharedFieldReferences[eth1DataVotes].Refs() > 1 { + if b.sharedFieldReferences[nativetypes.Eth1DataVotes].Refs() > 1 { // Copy elements in underlying array by reference. votes = make([]*ethpb.Eth1Data, len(b.eth1DataVotes)) copy(votes, b.eth1DataVotes) - b.sharedFieldReferences[eth1DataVotes].MinusRef() - b.sharedFieldReferences[eth1DataVotes] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.Eth1DataVotes].MinusRef() + b.sharedFieldReferences[nativetypes.Eth1DataVotes] = stateutil.NewRef(1) } b.eth1DataVotes = append(votes, val) - b.markFieldAsDirty(eth1DataVotes) - b.addDirtyIndices(eth1DataVotes, []uint64{uint64(len(b.eth1DataVotes) - 1)}) + b.markFieldAsDirty(nativetypes.Eth1DataVotes) + b.addDirtyIndices(nativetypes.Eth1DataVotes, []uint64{uint64(len(b.eth1DataVotes) - 1)}) return nil } diff --git a/beacon-chain/state/state-native/v1/setters_misc.go b/beacon-chain/state/state-native/setters_misc.go similarity index 84% rename from beacon-chain/state/state-native/v1/setters_misc.go rename to beacon-chain/state/state-native/setters_misc.go index fe4069ef98..00ebc4804c 100644 --- a/beacon-chain/state/state-native/v1/setters_misc.go +++ b/beacon-chain/state/state-native/setters_misc.go @@ -1,9 +1,9 @@ -package v1 +package state_native import ( "github.com/pkg/errors" + nativetypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/types" "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - stateTypes "github.com/prysmaticlabs/prysm/beacon-chain/state/types" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" types "github.com/prysmaticlabs/prysm/consensus-types/primitives" "github.com/prysmaticlabs/prysm/crypto/hash" @@ -46,7 +46,7 @@ func (b *BeaconState) SetGenesisTime(val uint64) error { defer b.lock.Unlock() b.genesisTime = val - b.markFieldAsDirty(genesisTime) + b.markFieldAsDirty(nativetypes.GenesisTime) return nil } @@ -59,7 +59,7 @@ func (b *BeaconState) SetGenesisValidatorsRoot(val []byte) error { return errors.New("incorrect validators root length") } b.genesisValidatorsRoot = bytesutil.ToBytes32(val) - b.markFieldAsDirty(genesisValidatorsRoot) + b.markFieldAsDirty(nativetypes.GenesisValidatorsRoot) return nil } @@ -69,7 +69,7 @@ func (b *BeaconState) SetSlot(val types.Slot) error { defer b.lock.Unlock() b.slot = val - b.markFieldAsDirty(slot) + b.markFieldAsDirty(nativetypes.Slot) return nil } @@ -83,7 +83,7 @@ func (b *BeaconState) SetFork(val *ethpb.Fork) error { return errors.New("proto.Clone did not return a fork proto") } b.fork = fk - b.markFieldAsDirty(fork) + b.markFieldAsDirty(nativetypes.Fork) return nil } @@ -93,15 +93,15 @@ func (b *BeaconState) SetHistoricalRoots(val [][]byte) error { b.lock.Lock() defer b.lock.Unlock() - b.sharedFieldReferences[historicalRoots].MinusRef() - b.sharedFieldReferences[historicalRoots] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.HistoricalRoots].MinusRef() + b.sharedFieldReferences[nativetypes.HistoricalRoots] = stateutil.NewRef(1) roots := make([][32]byte, len(val)) for i, r := range val { copy(roots[i][:], r) } b.historicalRoots = roots - b.markFieldAsDirty(historicalRoots) + b.markFieldAsDirty(nativetypes.HistoricalRoots) return nil } @@ -112,15 +112,15 @@ func (b *BeaconState) AppendHistoricalRoots(root [32]byte) error { defer b.lock.Unlock() roots := b.historicalRoots - if b.sharedFieldReferences[historicalRoots].Refs() > 1 { + if b.sharedFieldReferences[nativetypes.HistoricalRoots].Refs() > 1 { roots = make([][32]byte, len(b.historicalRoots)) copy(roots, b.historicalRoots) - b.sharedFieldReferences[historicalRoots].MinusRef() - b.sharedFieldReferences[historicalRoots] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.HistoricalRoots].MinusRef() + b.sharedFieldReferences[nativetypes.HistoricalRoots] = stateutil.NewRef(1) } b.historicalRoots = append(roots, root) - b.markFieldAsDirty(historicalRoots) + b.markFieldAsDirty(nativetypes.HistoricalRoots) return nil } @@ -159,13 +159,13 @@ func (b *BeaconState) recomputeRoot(idx int) { b.merkleLayers = layers } -func (b *BeaconState) markFieldAsDirty(field stateTypes.FieldIndex) { +func (b *BeaconState) markFieldAsDirty(field nativetypes.FieldIndex) { b.dirtyFields[field] = true } // addDirtyIndices adds the relevant dirty field indices, so that they // can be recomputed. -func (b *BeaconState) addDirtyIndices(index stateTypes.FieldIndex, indices []uint64) { +func (b *BeaconState) addDirtyIndices(index nativetypes.FieldIndex, indices []uint64) { if b.rebuildTrie[index] { return } diff --git a/beacon-chain/state/state-native/setters_participation.go b/beacon-chain/state/state-native/setters_participation.go new file mode 100644 index 0000000000..d121091074 --- /dev/null +++ b/beacon-chain/state/state-native/setters_participation.go @@ -0,0 +1,165 @@ +package state_native + +import ( + nativetypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/types" + "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" + "github.com/prysmaticlabs/prysm/runtime/version" +) + +// SetPreviousParticipationBits for the beacon state. Updates the entire +// list to a new value by overwriting the previous one. +func (b *BeaconState) SetPreviousParticipationBits(val []byte) error { + b.lock.Lock() + defer b.lock.Unlock() + + if b.version == version.Phase0 { + return errNotSupported("SetPreviousParticipationBits", b.version) + } + + b.sharedFieldReferences[nativetypes.PreviousEpochParticipationBits].MinusRef() + b.sharedFieldReferences[nativetypes.PreviousEpochParticipationBits] = stateutil.NewRef(1) + + b.previousEpochParticipation = val + b.markFieldAsDirty(nativetypes.PreviousEpochParticipationBits) + b.rebuildTrie[nativetypes.PreviousEpochParticipationBits] = true + return nil +} + +// SetCurrentParticipationBits for the beacon state. Updates the entire +// list to a new value by overwriting the previous one. +func (b *BeaconState) SetCurrentParticipationBits(val []byte) error { + b.lock.Lock() + defer b.lock.Unlock() + + if b.version == version.Phase0 { + return errNotSupported("SetCurrentParticipationBits", b.version) + } + + b.sharedFieldReferences[nativetypes.CurrentEpochParticipationBits].MinusRef() + b.sharedFieldReferences[nativetypes.CurrentEpochParticipationBits] = stateutil.NewRef(1) + + b.currentEpochParticipation = val + b.markFieldAsDirty(nativetypes.CurrentEpochParticipationBits) + b.rebuildTrie[nativetypes.CurrentEpochParticipationBits] = true + return nil +} + +// AppendCurrentParticipationBits for the beacon state. Appends the new value +// to the the end of list. +func (b *BeaconState) AppendCurrentParticipationBits(val byte) error { + b.lock.Lock() + defer b.lock.Unlock() + + if b.version == version.Phase0 { + return errNotSupported("AppendCurrentParticipationBits", b.version) + } + + participation := b.currentEpochParticipation + if b.sharedFieldReferences[nativetypes.CurrentEpochParticipationBits].Refs() > 1 { + // Copy elements in underlying array by reference. + participation = make([]byte, len(b.currentEpochParticipation)) + copy(participation, b.currentEpochParticipation) + b.sharedFieldReferences[nativetypes.CurrentEpochParticipationBits].MinusRef() + b.sharedFieldReferences[nativetypes.CurrentEpochParticipationBits] = stateutil.NewRef(1) + } + + b.currentEpochParticipation = append(participation, val) + b.markFieldAsDirty(nativetypes.CurrentEpochParticipationBits) + b.addDirtyIndices(nativetypes.CurrentEpochParticipationBits, []uint64{uint64(len(b.currentEpochParticipation) - 1)}) + return nil +} + +// AppendPreviousParticipationBits for the beacon state. Appends the new value +// to the the end of list. +func (b *BeaconState) AppendPreviousParticipationBits(val byte) error { + b.lock.Lock() + defer b.lock.Unlock() + + if b.version == version.Phase0 { + return errNotSupported("AppendPreviousParticipationBits", b.version) + } + + bits := b.previousEpochParticipation + if b.sharedFieldReferences[nativetypes.PreviousEpochParticipationBits].Refs() > 1 { + bits = make([]byte, len(b.previousEpochParticipation)) + copy(bits, b.previousEpochParticipation) + b.sharedFieldReferences[nativetypes.PreviousEpochParticipationBits].MinusRef() + b.sharedFieldReferences[nativetypes.PreviousEpochParticipationBits] = stateutil.NewRef(1) + } + + b.previousEpochParticipation = append(bits, val) + b.markFieldAsDirty(nativetypes.PreviousEpochParticipationBits) + b.addDirtyIndices(nativetypes.PreviousEpochParticipationBits, []uint64{uint64(len(b.previousEpochParticipation) - 1)}) + + return nil +} + +// ModifyPreviousParticipationBits modifies the previous participation bitfield via +// the provided mutator function. +func (b *BeaconState) ModifyPreviousParticipationBits(mutator func(val []byte) ([]byte, error)) error { + b.lock.Lock() + + if b.version == version.Phase0 { + b.lock.Unlock() + return errNotSupported("ModifyPreviousParticipationBits", b.version) + } + + participation := b.previousEpochParticipation + if b.sharedFieldReferences[nativetypes.PreviousEpochParticipationBits].Refs() > 1 { + // Copy elements in underlying array by reference. + participation = make([]byte, len(b.previousEpochParticipation)) + copy(participation, b.previousEpochParticipation) + b.sharedFieldReferences[nativetypes.PreviousEpochParticipationBits].MinusRef() + b.sharedFieldReferences[nativetypes.PreviousEpochParticipationBits] = stateutil.NewRef(1) + } + // Lock is released so that mutator can + // acquire it. + b.lock.Unlock() + + var err error + participation, err = mutator(participation) + if err != nil { + return err + } + b.lock.Lock() + defer b.lock.Unlock() + b.previousEpochParticipation = participation + b.markFieldAsDirty(nativetypes.PreviousEpochParticipationBits) + b.rebuildTrie[nativetypes.PreviousEpochParticipationBits] = true + return nil +} + +// ModifyCurrentParticipationBits modifies the current participation bitfield via +// the provided mutator function. +func (b *BeaconState) ModifyCurrentParticipationBits(mutator func(val []byte) ([]byte, error)) error { + b.lock.Lock() + + if b.version == version.Phase0 { + b.lock.Unlock() + return errNotSupported("ModifyCurrentParticipationBits", b.version) + } + + participation := b.currentEpochParticipation + if b.sharedFieldReferences[nativetypes.CurrentEpochParticipationBits].Refs() > 1 { + // Copy elements in underlying array by reference. + participation = make([]byte, len(b.currentEpochParticipation)) + copy(participation, b.currentEpochParticipation) + b.sharedFieldReferences[nativetypes.CurrentEpochParticipationBits].MinusRef() + b.sharedFieldReferences[nativetypes.CurrentEpochParticipationBits] = stateutil.NewRef(1) + } + // Lock is released so that mutator can + // acquire it. + b.lock.Unlock() + + var err error + participation, err = mutator(participation) + if err != nil { + return err + } + b.lock.Lock() + defer b.lock.Unlock() + b.currentEpochParticipation = participation + b.markFieldAsDirty(nativetypes.CurrentEpochParticipationBits) + b.rebuildTrie[nativetypes.CurrentEpochParticipationBits] = true + return nil +} diff --git a/beacon-chain/state/state-native/setters_payload_header.go b/beacon-chain/state/state-native/setters_payload_header.go new file mode 100644 index 0000000000..130d4265b3 --- /dev/null +++ b/beacon-chain/state/state-native/setters_payload_header.go @@ -0,0 +1,21 @@ +package state_native + +import ( + nativetypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/types" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/runtime/version" +) + +// SetLatestExecutionPayloadHeader for the beacon state. +func (b *BeaconState) SetLatestExecutionPayloadHeader(val *ethpb.ExecutionPayloadHeader) error { + b.lock.Lock() + defer b.lock.Unlock() + + if b.version == version.Phase0 || b.version == version.Altair { + return errNotSupported("SetLatestExecutionPayloadHeader", b.version) + } + + b.latestExecutionPayloadHeader = val + b.markFieldAsDirty(nativetypes.LatestExecutionPayloadHeader) + return nil +} diff --git a/beacon-chain/state/state-native/v1/setters_randao.go b/beacon-chain/state/state-native/setters_randao.go similarity index 66% rename from beacon-chain/state/state-native/v1/setters_randao.go rename to beacon-chain/state/state-native/setters_randao.go index 12f5112d36..1221881e8a 100644 --- a/beacon-chain/state/state-native/v1/setters_randao.go +++ b/beacon-chain/state/state-native/setters_randao.go @@ -1,8 +1,9 @@ -package v1 +package state_native import ( "github.com/pkg/errors" customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types" + nativetypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/types" "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/encoding/bytesutil" @@ -14,8 +15,8 @@ func (b *BeaconState) SetRandaoMixes(val [][]byte) error { b.lock.Lock() defer b.lock.Unlock() - b.sharedFieldReferences[randaoMixes].MinusRef() - b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.RandaoMixes].MinusRef() + b.sharedFieldReferences[nativetypes.RandaoMixes] = stateutil.NewRef(1) var mixesArr [fieldparams.RandaoMixesLength][32]byte for i := 0; i < len(mixesArr); i++ { @@ -23,8 +24,8 @@ func (b *BeaconState) SetRandaoMixes(val [][]byte) error { } mixes := customtypes.RandaoMixes(mixesArr) b.randaoMixes = &mixes - b.markFieldAsDirty(randaoMixes) - b.rebuildTrie[randaoMixes] = true + b.markFieldAsDirty(nativetypes.RandaoMixes) + b.rebuildTrie[nativetypes.RandaoMixes] = true return nil } @@ -38,19 +39,19 @@ func (b *BeaconState) UpdateRandaoMixesAtIndex(idx uint64, val []byte) error { defer b.lock.Unlock() mixes := b.randaoMixes - if refs := b.sharedFieldReferences[randaoMixes].Refs(); refs > 1 { + if refs := b.sharedFieldReferences[nativetypes.RandaoMixes].Refs(); refs > 1 { // Copy elements in underlying array by reference. m := *b.randaoMixes mCopy := m mixes = &mCopy - b.sharedFieldReferences[randaoMixes].MinusRef() - b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.RandaoMixes].MinusRef() + b.sharedFieldReferences[nativetypes.RandaoMixes] = stateutil.NewRef(1) } mixes[idx] = bytesutil.ToBytes32(val) b.randaoMixes = mixes - b.markFieldAsDirty(randaoMixes) - b.addDirtyIndices(randaoMixes, []uint64{idx}) + b.markFieldAsDirty(nativetypes.RandaoMixes) + b.addDirtyIndices(nativetypes.RandaoMixes, []uint64{idx}) return nil } diff --git a/beacon-chain/state/state-native/v1/setters_state.go b/beacon-chain/state/state-native/setters_state.go similarity index 69% rename from beacon-chain/state/state-native/v1/setters_state.go rename to beacon-chain/state/state-native/setters_state.go index b30803957b..bb41d3c7d7 100644 --- a/beacon-chain/state/state-native/v1/setters_state.go +++ b/beacon-chain/state/state-native/setters_state.go @@ -1,8 +1,9 @@ -package v1 +package state_native import ( "github.com/pkg/errors" customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types" + nativetypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/types" "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" ) @@ -13,8 +14,8 @@ func (b *BeaconState) SetStateRoots(val [][]byte) error { b.lock.Lock() defer b.lock.Unlock() - b.sharedFieldReferences[stateRoots].MinusRef() - b.sharedFieldReferences[stateRoots] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.StateRoots].MinusRef() + b.sharedFieldReferences[nativetypes.StateRoots] = stateutil.NewRef(1) var rootsArr [fieldparams.StateRootsLength][32]byte for i := 0; i < len(rootsArr); i++ { @@ -22,8 +23,8 @@ func (b *BeaconState) SetStateRoots(val [][]byte) error { } roots := customtypes.StateRoots(rootsArr) b.stateRoots = &roots - b.markFieldAsDirty(stateRoots) - b.rebuildTrie[stateRoots] = true + b.markFieldAsDirty(nativetypes.StateRoots) + b.rebuildTrie[nativetypes.StateRoots] = true return nil } @@ -42,19 +43,19 @@ func (b *BeaconState) UpdateStateRootAtIndex(idx uint64, stateRoot [32]byte) err // Check if we hold the only reference to the shared state roots slice. r := b.stateRoots - if ref := b.sharedFieldReferences[stateRoots]; ref.Refs() > 1 { + if ref := b.sharedFieldReferences[nativetypes.StateRoots]; ref.Refs() > 1 { // Copy elements in underlying array by reference. roots := *b.stateRoots rootsCopy := roots r = &rootsCopy ref.MinusRef() - b.sharedFieldReferences[stateRoots] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.StateRoots] = stateutil.NewRef(1) } r[idx] = stateRoot b.stateRoots = r - b.markFieldAsDirty(stateRoots) - b.addDirtyIndices(stateRoots, []uint64{idx}) + b.markFieldAsDirty(nativetypes.StateRoots) + b.addDirtyIndices(nativetypes.StateRoots, []uint64{idx}) return nil } diff --git a/beacon-chain/state/state-native/v3/setters_sync_committee.go b/beacon-chain/state/state-native/setters_sync_committee.go similarity index 51% rename from beacon-chain/state/state-native/v3/setters_sync_committee.go rename to beacon-chain/state/state-native/setters_sync_committee.go index 2cf694a821..cec9b36318 100644 --- a/beacon-chain/state/state-native/v3/setters_sync_committee.go +++ b/beacon-chain/state/state-native/setters_sync_committee.go @@ -1,7 +1,9 @@ -package v3 +package state_native import ( + nativetypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/types" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/runtime/version" ) // SetCurrentSyncCommittee for the beacon state. @@ -9,8 +11,12 @@ func (b *BeaconState) SetCurrentSyncCommittee(val *ethpb.SyncCommittee) error { b.lock.Lock() defer b.lock.Unlock() + if b.version == version.Phase0 { + return errNotSupported("SetCurrentSyncCommittee", b.version) + } + b.currentSyncCommittee = val - b.markFieldAsDirty(currentSyncCommittee) + b.markFieldAsDirty(nativetypes.CurrentSyncCommittee) return nil } @@ -19,7 +25,11 @@ func (b *BeaconState) SetNextSyncCommittee(val *ethpb.SyncCommittee) error { b.lock.Lock() defer b.lock.Unlock() + if b.version == version.Phase0 { + return errNotSupported("SetNextSyncCommittee", b.version) + } + b.nextSyncCommittee = val - b.markFieldAsDirty(nextSyncCommittee) + b.markFieldAsDirty(nativetypes.NextSyncCommittee) return nil } diff --git a/beacon-chain/state/state-native/v3/setters_validator.go b/beacon-chain/state/state-native/setters_validator.go similarity index 58% rename from beacon-chain/state/state-native/v3/setters_validator.go rename to beacon-chain/state/state-native/setters_validator.go index 03e6b8381d..d79a704ba8 100644 --- a/beacon-chain/state/state-native/v3/setters_validator.go +++ b/beacon-chain/state/state-native/setters_validator.go @@ -1,11 +1,13 @@ -package v3 +package state_native import ( "github.com/pkg/errors" + nativetypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/types" "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" types "github.com/prysmaticlabs/prysm/consensus-types/primitives" "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/runtime/version" ) // SetValidators for the beacon state. Updates the entire @@ -15,10 +17,10 @@ func (b *BeaconState) SetValidators(val []*ethpb.Validator) error { defer b.lock.Unlock() b.validators = val - b.sharedFieldReferences[validators].MinusRef() - b.sharedFieldReferences[validators] = stateutil.NewRef(1) - b.markFieldAsDirty(validators) - b.rebuildTrie[validators] = true + b.sharedFieldReferences[nativetypes.Validators].MinusRef() + b.sharedFieldReferences[nativetypes.Validators] = stateutil.NewRef(1) + b.markFieldAsDirty(nativetypes.Validators) + b.rebuildTrie[nativetypes.Validators] = true b.valMapHandler = stateutil.NewValMapHandler(b.validators) return nil } @@ -28,10 +30,10 @@ func (b *BeaconState) SetValidators(val []*ethpb.Validator) error { func (b *BeaconState) ApplyToEveryValidator(f func(idx int, val *ethpb.Validator) (bool, *ethpb.Validator, error)) error { b.lock.Lock() v := b.validators - if ref := b.sharedFieldReferences[validators]; ref.Refs() > 1 { + if ref := b.sharedFieldReferences[nativetypes.Validators]; ref.Refs() > 1 { v = b.validatorsReferences() ref.MinusRef() - b.sharedFieldReferences[validators] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.Validators] = stateutil.NewRef(1) } b.lock.Unlock() var changedVals []uint64 @@ -50,8 +52,8 @@ func (b *BeaconState) ApplyToEveryValidator(f func(idx int, val *ethpb.Validator defer b.lock.Unlock() b.validators = v - b.markFieldAsDirty(validators) - b.addDirtyIndices(validators, changedVals) + b.markFieldAsDirty(nativetypes.Validators) + b.addDirtyIndices(nativetypes.Validators, changedVals) return nil } @@ -66,16 +68,16 @@ func (b *BeaconState) UpdateValidatorAtIndex(idx types.ValidatorIndex, val *ethp defer b.lock.Unlock() v := b.validators - if ref := b.sharedFieldReferences[validators]; ref.Refs() > 1 { + if ref := b.sharedFieldReferences[nativetypes.Validators]; ref.Refs() > 1 { v = b.validatorsReferences() ref.MinusRef() - b.sharedFieldReferences[validators] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.Validators] = stateutil.NewRef(1) } v[idx] = val b.validators = v - b.markFieldAsDirty(validators) - b.addDirtyIndices(validators, []uint64{uint64(idx)}) + b.markFieldAsDirty(nativetypes.Validators) + b.addDirtyIndices(nativetypes.Validators, []uint64{uint64(idx)}) return nil } @@ -86,12 +88,12 @@ func (b *BeaconState) SetBalances(val []uint64) error { b.lock.Lock() defer b.lock.Unlock() - b.sharedFieldReferences[balances].MinusRef() - b.sharedFieldReferences[balances] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.Balances].MinusRef() + b.sharedFieldReferences[nativetypes.Balances] = stateutil.NewRef(1) b.balances = val - b.markFieldAsDirty(balances) - b.rebuildTrie[balances] = true + b.markFieldAsDirty(nativetypes.Balances) + b.rebuildTrie[nativetypes.Balances] = true return nil } @@ -105,16 +107,16 @@ func (b *BeaconState) UpdateBalancesAtIndex(idx types.ValidatorIndex, val uint64 defer b.lock.Unlock() bals := b.balances - if b.sharedFieldReferences[balances].Refs() > 1 { + if b.sharedFieldReferences[nativetypes.Balances].Refs() > 1 { bals = b.balancesVal() - b.sharedFieldReferences[balances].MinusRef() - b.sharedFieldReferences[balances] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.Balances].MinusRef() + b.sharedFieldReferences[nativetypes.Balances] = stateutil.NewRef(1) } bals[idx] = val b.balances = bals - b.markFieldAsDirty(balances) - b.addDirtyIndices(balances, []uint64{uint64(idx)}) + b.markFieldAsDirty(nativetypes.Balances) + b.addDirtyIndices(nativetypes.Balances, []uint64{uint64(idx)}) return nil } @@ -124,11 +126,11 @@ func (b *BeaconState) SetSlashings(val []uint64) error { b.lock.Lock() defer b.lock.Unlock() - b.sharedFieldReferences[slashings].MinusRef() - b.sharedFieldReferences[slashings] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.Slashings].MinusRef() + b.sharedFieldReferences[nativetypes.Slashings] = stateutil.NewRef(1) b.slashings = val - b.markFieldAsDirty(slashings) + b.markFieldAsDirty(nativetypes.Slashings) return nil } @@ -142,17 +144,17 @@ func (b *BeaconState) UpdateSlashingsAtIndex(idx, val uint64) error { defer b.lock.Unlock() s := b.slashings - if b.sharedFieldReferences[slashings].Refs() > 1 { + if b.sharedFieldReferences[nativetypes.Slashings].Refs() > 1 { s = b.slashingsVal() - b.sharedFieldReferences[slashings].MinusRef() - b.sharedFieldReferences[slashings] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.Slashings].MinusRef() + b.sharedFieldReferences[nativetypes.Slashings] = stateutil.NewRef(1) } s[idx] = val b.slashings = s - b.markFieldAsDirty(slashings) + b.markFieldAsDirty(nativetypes.Slashings) return nil } @@ -163,10 +165,10 @@ func (b *BeaconState) AppendValidator(val *ethpb.Validator) error { defer b.lock.Unlock() vals := b.validators - if b.sharedFieldReferences[validators].Refs() > 1 { + if b.sharedFieldReferences[nativetypes.Validators].Refs() > 1 { vals = b.validatorsReferences() - b.sharedFieldReferences[validators].MinusRef() - b.sharedFieldReferences[validators] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.Validators].MinusRef() + b.sharedFieldReferences[nativetypes.Validators] = stateutil.NewRef(1) } // append validator to slice @@ -175,8 +177,8 @@ func (b *BeaconState) AppendValidator(val *ethpb.Validator) error { b.valMapHandler.Set(bytesutil.ToBytes48(val.PublicKey), valIdx) - b.markFieldAsDirty(validators) - b.addDirtyIndices(validators, []uint64{uint64(valIdx)}) + b.markFieldAsDirty(nativetypes.Validators) + b.addDirtyIndices(nativetypes.Validators, []uint64{uint64(valIdx)}) return nil } @@ -187,16 +189,16 @@ func (b *BeaconState) AppendBalance(bal uint64) error { defer b.lock.Unlock() bals := b.balances - if b.sharedFieldReferences[balances].Refs() > 1 { + if b.sharedFieldReferences[nativetypes.Balances].Refs() > 1 { bals = b.balancesVal() - b.sharedFieldReferences[balances].MinusRef() - b.sharedFieldReferences[balances] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.Balances].MinusRef() + b.sharedFieldReferences[nativetypes.Balances] = stateutil.NewRef(1) } b.balances = append(bals, bal) balIdx := len(b.balances) - 1 - b.markFieldAsDirty(balances) - b.addDirtyIndices(balances, []uint64{uint64(balIdx)}) + b.markFieldAsDirty(nativetypes.Balances) + b.addDirtyIndices(nativetypes.Balances, []uint64{uint64(balIdx)}) return nil } @@ -205,15 +207,19 @@ func (b *BeaconState) AppendInactivityScore(s uint64) error { b.lock.Lock() defer b.lock.Unlock() + if b.version == version.Phase0 { + return errNotSupported("AppendInactivityScore", b.version) + } + scores := b.inactivityScores - if b.sharedFieldReferences[inactivityScores].Refs() > 1 { + if b.sharedFieldReferences[nativetypes.InactivityScores].Refs() > 1 { scores = b.inactivityScoresVal() - b.sharedFieldReferences[inactivityScores].MinusRef() - b.sharedFieldReferences[inactivityScores] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.InactivityScores].MinusRef() + b.sharedFieldReferences[nativetypes.InactivityScores] = stateutil.NewRef(1) } b.inactivityScores = append(scores, s) - b.markFieldAsDirty(inactivityScores) + b.markFieldAsDirty(nativetypes.InactivityScores) return nil } @@ -223,10 +229,14 @@ func (b *BeaconState) SetInactivityScores(val []uint64) error { b.lock.Lock() defer b.lock.Unlock() - b.sharedFieldReferences[inactivityScores].MinusRef() - b.sharedFieldReferences[inactivityScores] = stateutil.NewRef(1) + if b.version == version.Phase0 { + return errNotSupported("SetInactivityScores", b.version) + } + + b.sharedFieldReferences[nativetypes.InactivityScores].MinusRef() + b.sharedFieldReferences[nativetypes.InactivityScores] = stateutil.NewRef(1) b.inactivityScores = val - b.markFieldAsDirty(inactivityScores) + b.markFieldAsDirty(nativetypes.InactivityScores) return nil } diff --git a/beacon-chain/state/state-native/ssz.go b/beacon-chain/state/state-native/ssz.go new file mode 100644 index 0000000000..1c3ab7ea4c --- /dev/null +++ b/beacon-chain/state/state-native/ssz.go @@ -0,0 +1,36 @@ +package state_native + +import ( + "github.com/pkg/errors" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/runtime/version" +) + +var errAssertionFailed = errors.New("failed to convert interface to proto state") +var errUnsupportedVersion = errors.New("unsupported beacon state version") + +func (b *BeaconState) MarshalSSZ() ([]byte, error) { + proto := b.ToProto() + switch b.Version() { + case version.Phase0: + s, ok := proto.(*ethpb.BeaconState) + if !ok { + return nil, errAssertionFailed + } + return s.MarshalSSZ() + case version.Altair: + s, ok := proto.(*ethpb.BeaconStateAltair) + if !ok { + return nil, errAssertionFailed + } + return s.MarshalSSZ() + case version.Bellatrix: + s, ok := proto.(*ethpb.BeaconStateBellatrix) + if !ok { + return nil, errAssertionFailed + } + return s.MarshalSSZ() + default: + return nil, errUnsupportedVersion + } +} diff --git a/beacon-chain/state/state-native/v1/state_test.go b/beacon-chain/state/state-native/state_test.go similarity index 62% rename from beacon-chain/state/state-native/v1/state_test.go rename to beacon-chain/state/state-native/state_test.go index 0ebda0495e..4aefeb494f 100644 --- a/beacon-chain/state/state-native/v1/state_test.go +++ b/beacon-chain/state/state-native/state_test.go @@ -1,4 +1,4 @@ -package v1 +package state_native import ( "context" @@ -7,6 +7,7 @@ import ( "testing" "github.com/prysmaticlabs/go-bitfield" + nativetypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/types" "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/config/params" @@ -45,7 +46,7 @@ func TestValidatorMap_DistinctCopy(t *testing.T) { assert.NotEqual(t, val1, val2, "Values are supposed to be unequal due to copy") } -func TestBeaconState_NoDeadlock(t *testing.T) { +func TestBeaconState_NoDeadlock_Phase0(t *testing.T) { count := uint64(100) vals := make([]*ethpb.Validator, 0, count) for i := uint64(1); i < count; i++ { @@ -64,7 +65,63 @@ func TestBeaconState_NoDeadlock(t *testing.T) { WithdrawableEpoch: 1, }) } - st, err := InitializeFromProtoUnsafe(ðpb.BeaconState{ + newState, err := InitializeFromProtoUnsafePhase0(ðpb.BeaconState{ + Validators: vals, + }) + assert.NoError(t, err) + st, ok := newState.(*BeaconState) + require.Equal(t, true, ok) + + wg := new(sync.WaitGroup) + + wg.Add(1) + go func() { + // Continuously lock and unlock the state + // by acquiring the lock. + for i := 0; i < 1000; i++ { + for _, f := range st.stateFieldLeaves { + f.Lock() + if f.Empty() { + f.InsertFieldLayer(make([][]*[32]byte, 10)) + } + f.Unlock() + f.FieldReference().AddRef() + } + } + wg.Done() + }() + // Constantly read from the offending portion + // of the code to ensure there is no possible + // recursive read locking. + for i := 0; i < 1000; i++ { + go func() { + _ = st.FieldReferencesCount() + }() + } + // Test will not terminate in the event of a deadlock. + wg.Wait() +} + +func TestBeaconState_NoDeadlock_Altair(t *testing.T) { + count := uint64(100) + vals := make([]*ethpb.Validator, 0, count) + for i := uint64(1); i < count; i++ { + someRoot := [32]byte{} + someKey := [fieldparams.BLSPubkeyLength]byte{} + copy(someRoot[:], strconv.Itoa(int(i))) + copy(someKey[:], strconv.Itoa(int(i))) + vals = append(vals, ðpb.Validator{ + PublicKey: someKey[:], + WithdrawalCredentials: someRoot[:], + EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, + Slashed: false, + ActivationEligibilityEpoch: 1, + ActivationEpoch: 1, + ExitEpoch: 1, + WithdrawableEpoch: 1, + }) + } + st, err := InitializeFromProtoUnsafeAltair(ðpb.BeaconStateAltair{ Validators: vals, }) assert.NoError(t, err) @@ -101,9 +158,60 @@ func TestBeaconState_NoDeadlock(t *testing.T) { wg.Wait() } -func TestStateTrie_IsNil(t *testing.T) { - var emptyState *BeaconState - assert.Equal(t, true, emptyState.IsNil()) +func TestBeaconState_NoDeadlock_Bellatrix(t *testing.T) { + count := uint64(100) + vals := make([]*ethpb.Validator, 0, count) + for i := uint64(1); i < count; i++ { + someRoot := [32]byte{} + someKey := [fieldparams.BLSPubkeyLength]byte{} + copy(someRoot[:], strconv.Itoa(int(i))) + copy(someKey[:], strconv.Itoa(int(i))) + vals = append(vals, ðpb.Validator{ + PublicKey: someKey[:], + WithdrawalCredentials: someRoot[:], + EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, + Slashed: false, + ActivationEligibilityEpoch: 1, + ActivationEpoch: 1, + ExitEpoch: 1, + WithdrawableEpoch: 1, + }) + } + st, err := InitializeFromProtoUnsafeBellatrix(ðpb.BeaconStateBellatrix{ + Validators: vals, + }) + assert.NoError(t, err) + s, ok := st.(*BeaconState) + require.Equal(t, true, ok) + + wg := new(sync.WaitGroup) + + wg.Add(1) + go func() { + // Continuously lock and unlock the state + // by acquiring the lock. + for i := 0; i < 1000; i++ { + for _, f := range s.stateFieldLeaves { + f.Lock() + if f.Empty() { + f.InsertFieldLayer(make([][]*[32]byte, 10)) + } + f.Unlock() + f.FieldReference().AddRef() + } + } + wg.Done() + }() + // Constantly read from the offending portion + // of the code to ensure there is no possible + // recursive read locking. + for i := 0; i < 1000; i++ { + go func() { + _ = st.FieldReferencesCount() + }() + } + // Test will not terminate in the event of a deadlock. + wg.Wait() } func TestBeaconState_AppendBalanceWithTrie(t *testing.T) { @@ -141,7 +249,7 @@ func TestBeaconState_AppendBalanceWithTrie(t *testing.T) { for i := 0; i < len(mockrandaoMixes); i++ { mockrandaoMixes[i] = zeroHash[:] } - st, err := InitializeFromProto(ðpb.BeaconState{ + newState, err := InitializeFromProtoPhase0(ðpb.BeaconState{ Slot: 1, GenesisValidatorsRoot: make([]byte, 32), Fork: ðpb.Fork{ @@ -170,6 +278,8 @@ func TestBeaconState_AppendBalanceWithTrie(t *testing.T) { Slashings: make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector), }) assert.NoError(t, err) + st, ok := newState.(*BeaconState) + require.Equal(t, true, ok) _, err = st.HashTreeRoot(context.Background()) assert.NoError(t, err) @@ -183,26 +293,24 @@ func TestBeaconState_AppendBalanceWithTrie(t *testing.T) { } _, err = st.HashTreeRoot(context.Background()) assert.NoError(t, err) - s, ok := st.(*BeaconState) - require.Equal(t, true, ok) - newRt := bytesutil.ToBytes32(s.merkleLayers[0][balances]) - wantedRt, err := stateutil.Uint64ListRootWithRegistryLimit(s.Balances()) + newRt := bytesutil.ToBytes32(st.merkleLayers[0][nativetypes.Balances]) + wantedRt, err := stateutil.Uint64ListRootWithRegistryLimit(st.Balances()) assert.NoError(t, err) assert.Equal(t, wantedRt, newRt, "state roots are unequal") } func TestBeaconState_ModifyPreviousParticipationBits(t *testing.T) { - st, err := InitializeFromProtoUnsafe(ðpb.BeaconState{}) + st, err := InitializeFromProtoUnsafePhase0(ðpb.BeaconState{}) assert.NoError(t, err) - assert.ErrorContains(t, "ModifyPreviousParticipationBits is not supported for phase 0 beacon state", st.ModifyPreviousParticipationBits(func(val []byte) ([]byte, error) { + assert.ErrorContains(t, "ModifyPreviousParticipationBits is not supported", st.ModifyPreviousParticipationBits(func(val []byte) ([]byte, error) { return nil, nil })) } func TestBeaconState_ModifyCurrentParticipationBits(t *testing.T) { - st, err := InitializeFromProtoUnsafe(ðpb.BeaconState{}) + st, err := InitializeFromProtoUnsafePhase0(ðpb.BeaconState{}) assert.NoError(t, err) - assert.ErrorContains(t, "ModifyCurrentParticipationBits is not supported for phase 0 beacon state", st.ModifyCurrentParticipationBits(func(val []byte) ([]byte, error) { + assert.ErrorContains(t, "ModifyCurrentParticipationBits is not supported", st.ModifyCurrentParticipationBits(func(val []byte) ([]byte, error) { return nil, nil })) } diff --git a/beacon-chain/state/state-native/state_trie.go b/beacon-chain/state/state-native/state_trie.go new file mode 100644 index 0000000000..bd88d3a947 --- /dev/null +++ b/beacon-chain/state/state-native/state_trie.go @@ -0,0 +1,792 @@ +package state_native + +import ( + "context" + "runtime" + "sort" + + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state/fieldtrie" + customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types" + nativetypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/types" + "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" + "github.com/prysmaticlabs/prysm/beacon-chain/state/types" + fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" + "github.com/prysmaticlabs/prysm/config/params" + "github.com/prysmaticlabs/prysm/container/slice" + "github.com/prysmaticlabs/prysm/crypto/hash" + "github.com/prysmaticlabs/prysm/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/encoding/ssz" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/runtime/version" + "go.opencensus.io/trace" + "google.golang.org/protobuf/proto" +) + +var phase0Fields = []nativetypes.FieldIndex{ + nativetypes.GenesisTime, + nativetypes.GenesisValidatorsRoot, + nativetypes.Slot, + nativetypes.Fork, + nativetypes.LatestBlockHeader, + nativetypes.BlockRoots, + nativetypes.StateRoots, + nativetypes.HistoricalRoots, + nativetypes.Eth1Data, + nativetypes.Eth1DataVotes, + nativetypes.Eth1DepositIndex, + nativetypes.Validators, + nativetypes.Balances, + nativetypes.RandaoMixes, + nativetypes.Slashings, + nativetypes.PreviousEpochAttestations, + nativetypes.CurrentEpochAttestations, + nativetypes.JustificationBits, + nativetypes.PreviousJustifiedCheckpoint, + nativetypes.CurrentJustifiedCheckpoint, + nativetypes.FinalizedCheckpoint, +} + +var altairFields = []nativetypes.FieldIndex{ + nativetypes.GenesisTime, + nativetypes.GenesisValidatorsRoot, + nativetypes.Slot, + nativetypes.Fork, + nativetypes.LatestBlockHeader, + nativetypes.BlockRoots, + nativetypes.StateRoots, + nativetypes.HistoricalRoots, + nativetypes.Eth1Data, + nativetypes.Eth1DataVotes, + nativetypes.Eth1DepositIndex, + nativetypes.Validators, + nativetypes.Balances, + nativetypes.RandaoMixes, + nativetypes.Slashings, + nativetypes.PreviousEpochParticipationBits, + nativetypes.CurrentEpochParticipationBits, + nativetypes.JustificationBits, + nativetypes.PreviousJustifiedCheckpoint, + nativetypes.CurrentJustifiedCheckpoint, + nativetypes.FinalizedCheckpoint, + nativetypes.InactivityScores, + nativetypes.CurrentSyncCommittee, + nativetypes.NextSyncCommittee, +} + +var bellatrixFields = []nativetypes.FieldIndex{ + nativetypes.GenesisTime, + nativetypes.GenesisValidatorsRoot, + nativetypes.Slot, + nativetypes.Fork, + nativetypes.LatestBlockHeader, + nativetypes.BlockRoots, + nativetypes.StateRoots, + nativetypes.HistoricalRoots, + nativetypes.Eth1Data, + nativetypes.Eth1DataVotes, + nativetypes.Eth1DepositIndex, + nativetypes.Validators, + nativetypes.Balances, + nativetypes.RandaoMixes, + nativetypes.Slashings, + nativetypes.PreviousEpochParticipationBits, + nativetypes.CurrentEpochParticipationBits, + nativetypes.JustificationBits, + nativetypes.PreviousJustifiedCheckpoint, + nativetypes.CurrentJustifiedCheckpoint, + nativetypes.FinalizedCheckpoint, + nativetypes.InactivityScores, + nativetypes.CurrentSyncCommittee, + nativetypes.NextSyncCommittee, + nativetypes.LatestExecutionPayloadHeader, +} + +// InitializeFromProtoPhase0 the beacon state from a protobuf representation. +func InitializeFromProtoPhase0(st *ethpb.BeaconState) (state.BeaconState, error) { + return InitializeFromProtoUnsafePhase0(proto.Clone(st).(*ethpb.BeaconState)) +} + +// InitializeFromProtoAltair the beacon state from a protobuf representation. +func InitializeFromProtoAltair(st *ethpb.BeaconStateAltair) (state.BeaconState, error) { + return InitializeFromProtoUnsafeAltair(proto.Clone(st).(*ethpb.BeaconStateAltair)) +} + +// InitializeFromProtoBellatrix the beacon state from a protobuf representation. +func InitializeFromProtoBellatrix(st *ethpb.BeaconStateBellatrix) (state.BeaconState, error) { + return InitializeFromProtoUnsafeBellatrix(proto.Clone(st).(*ethpb.BeaconStateBellatrix)) +} + +// InitializeFromProtoUnsafePhase0 directly uses the beacon state protobuf fields +// and sets them as fields of the BeaconState type. +func InitializeFromProtoUnsafePhase0(st *ethpb.BeaconState) (state.BeaconState, error) { + if st == nil { + return nil, errors.New("received nil state") + } + + var bRoots customtypes.BlockRoots + for i, r := range st.BlockRoots { + copy(bRoots[i][:], r) + } + var sRoots customtypes.StateRoots + for i, r := range st.StateRoots { + copy(sRoots[i][:], r) + } + hRoots := customtypes.HistoricalRoots(make([][32]byte, len(st.HistoricalRoots))) + for i, r := range st.HistoricalRoots { + copy(hRoots[i][:], r) + } + var mixes customtypes.RandaoMixes + for i, m := range st.RandaoMixes { + copy(mixes[i][:], m) + } + + fieldCount := params.BeaconConfig().BeaconStateFieldCount + b := &BeaconState{ + version: version.Phase0, + genesisTime: st.GenesisTime, + genesisValidatorsRoot: bytesutil.ToBytes32(st.GenesisValidatorsRoot), + slot: st.Slot, + fork: st.Fork, + latestBlockHeader: st.LatestBlockHeader, + blockRoots: &bRoots, + stateRoots: &sRoots, + historicalRoots: hRoots, + eth1Data: st.Eth1Data, + eth1DataVotes: st.Eth1DataVotes, + eth1DepositIndex: st.Eth1DepositIndex, + validators: st.Validators, + balances: st.Balances, + randaoMixes: &mixes, + slashings: st.Slashings, + previousEpochAttestations: st.PreviousEpochAttestations, + currentEpochAttestations: st.CurrentEpochAttestations, + justificationBits: st.JustificationBits, + previousJustifiedCheckpoint: st.PreviousJustifiedCheckpoint, + currentJustifiedCheckpoint: st.CurrentJustifiedCheckpoint, + finalizedCheckpoint: st.FinalizedCheckpoint, + + dirtyFields: make(map[nativetypes.FieldIndex]bool, fieldCount), + dirtyIndices: make(map[nativetypes.FieldIndex][]uint64, fieldCount), + stateFieldLeaves: make(map[nativetypes.FieldIndex]*fieldtrie.FieldTrie, fieldCount), + sharedFieldReferences: make(map[nativetypes.FieldIndex]*stateutil.Reference, 10), + rebuildTrie: make(map[nativetypes.FieldIndex]bool, fieldCount), + valMapHandler: stateutil.NewValMapHandler(st.Validators), + } + + for _, f := range phase0Fields { + b.dirtyFields[f] = true + b.rebuildTrie[f] = true + b.dirtyIndices[f] = []uint64{} + trie, err := fieldtrie.NewFieldTrie(f, types.BasicArray, nil, 0) + if err != nil { + return nil, err + } + b.stateFieldLeaves[f] = trie + } + + // Initialize field reference tracking for shared data. + b.sharedFieldReferences[nativetypes.BlockRoots] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.StateRoots] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.HistoricalRoots] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.Eth1DataVotes] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.Validators] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.Balances] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.RandaoMixes] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.Slashings] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.PreviousEpochAttestations] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.CurrentEpochAttestations] = stateutil.NewRef(1) + + state.StateCount.Inc() + return b, nil +} + +// InitializeFromProtoUnsafeAltair directly uses the beacon state protobuf fields +// and sets them as fields of the BeaconState type. +func InitializeFromProtoUnsafeAltair(st *ethpb.BeaconStateAltair) (state.BeaconStateAltair, error) { + if st == nil { + return nil, errors.New("received nil state") + } + + var bRoots customtypes.BlockRoots + for i, r := range st.BlockRoots { + bRoots[i] = bytesutil.ToBytes32(r) + } + var sRoots customtypes.StateRoots + for i, r := range st.StateRoots { + sRoots[i] = bytesutil.ToBytes32(r) + } + hRoots := customtypes.HistoricalRoots(make([][32]byte, len(st.HistoricalRoots))) + for i, r := range st.HistoricalRoots { + hRoots[i] = bytesutil.ToBytes32(r) + } + var mixes customtypes.RandaoMixes + for i, m := range st.RandaoMixes { + mixes[i] = bytesutil.ToBytes32(m) + } + + fieldCount := params.BeaconConfig().BeaconStateAltairFieldCount + b := &BeaconState{ + version: version.Altair, + genesisTime: st.GenesisTime, + genesisValidatorsRoot: bytesutil.ToBytes32(st.GenesisValidatorsRoot), + slot: st.Slot, + fork: st.Fork, + latestBlockHeader: st.LatestBlockHeader, + blockRoots: &bRoots, + stateRoots: &sRoots, + historicalRoots: hRoots, + eth1Data: st.Eth1Data, + eth1DataVotes: st.Eth1DataVotes, + eth1DepositIndex: st.Eth1DepositIndex, + validators: st.Validators, + balances: st.Balances, + randaoMixes: &mixes, + slashings: st.Slashings, + previousEpochParticipation: st.PreviousEpochParticipation, + currentEpochParticipation: st.CurrentEpochParticipation, + justificationBits: st.JustificationBits, + previousJustifiedCheckpoint: st.PreviousJustifiedCheckpoint, + currentJustifiedCheckpoint: st.CurrentJustifiedCheckpoint, + finalizedCheckpoint: st.FinalizedCheckpoint, + inactivityScores: st.InactivityScores, + currentSyncCommittee: st.CurrentSyncCommittee, + nextSyncCommittee: st.NextSyncCommittee, + + dirtyFields: make(map[nativetypes.FieldIndex]bool, fieldCount), + dirtyIndices: make(map[nativetypes.FieldIndex][]uint64, fieldCount), + stateFieldLeaves: make(map[nativetypes.FieldIndex]*fieldtrie.FieldTrie, fieldCount), + sharedFieldReferences: make(map[nativetypes.FieldIndex]*stateutil.Reference, 11), + rebuildTrie: make(map[nativetypes.FieldIndex]bool, fieldCount), + valMapHandler: stateutil.NewValMapHandler(st.Validators), + } + + for _, f := range altairFields { + b.dirtyFields[f] = true + b.rebuildTrie[f] = true + b.dirtyIndices[f] = []uint64{} + trie, err := fieldtrie.NewFieldTrie(f, types.BasicArray, nil, 0) + if err != nil { + return nil, err + } + b.stateFieldLeaves[f] = trie + } + + // Initialize field reference tracking for shared data. + b.sharedFieldReferences[nativetypes.BlockRoots] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.StateRoots] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.HistoricalRoots] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.Eth1DataVotes] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.Validators] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.Balances] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.RandaoMixes] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.Slashings] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.PreviousEpochParticipationBits] = stateutil.NewRef(1) // New in Altair. + b.sharedFieldReferences[nativetypes.CurrentEpochParticipationBits] = stateutil.NewRef(1) // New in Altair. + b.sharedFieldReferences[nativetypes.InactivityScores] = stateutil.NewRef(1) // New in Altair. + + state.StateCount.Inc() + return b, nil +} + +// InitializeFromProtoUnsafeBellatrix directly uses the beacon state protobuf fields +// and sets them as fields of the BeaconState type. +func InitializeFromProtoUnsafeBellatrix(st *ethpb.BeaconStateBellatrix) (state.BeaconStateBellatrix, error) { + if st == nil { + return nil, errors.New("received nil state") + } + + var bRoots customtypes.BlockRoots + for i, r := range st.BlockRoots { + bRoots[i] = bytesutil.ToBytes32(r) + } + var sRoots customtypes.StateRoots + for i, r := range st.StateRoots { + sRoots[i] = bytesutil.ToBytes32(r) + } + hRoots := customtypes.HistoricalRoots(make([][32]byte, len(st.HistoricalRoots))) + for i, r := range st.HistoricalRoots { + hRoots[i] = bytesutil.ToBytes32(r) + } + var mixes customtypes.RandaoMixes + for i, m := range st.RandaoMixes { + mixes[i] = bytesutil.ToBytes32(m) + } + + fieldCount := params.BeaconConfig().BeaconStateBellatrixFieldCount + b := &BeaconState{ + version: version.Bellatrix, + genesisTime: st.GenesisTime, + genesisValidatorsRoot: bytesutil.ToBytes32(st.GenesisValidatorsRoot), + slot: st.Slot, + fork: st.Fork, + latestBlockHeader: st.LatestBlockHeader, + blockRoots: &bRoots, + stateRoots: &sRoots, + historicalRoots: hRoots, + eth1Data: st.Eth1Data, + eth1DataVotes: st.Eth1DataVotes, + eth1DepositIndex: st.Eth1DepositIndex, + validators: st.Validators, + balances: st.Balances, + randaoMixes: &mixes, + slashings: st.Slashings, + previousEpochParticipation: st.PreviousEpochParticipation, + currentEpochParticipation: st.CurrentEpochParticipation, + justificationBits: st.JustificationBits, + previousJustifiedCheckpoint: st.PreviousJustifiedCheckpoint, + currentJustifiedCheckpoint: st.CurrentJustifiedCheckpoint, + finalizedCheckpoint: st.FinalizedCheckpoint, + inactivityScores: st.InactivityScores, + currentSyncCommittee: st.CurrentSyncCommittee, + nextSyncCommittee: st.NextSyncCommittee, + latestExecutionPayloadHeader: st.LatestExecutionPayloadHeader, + + dirtyFields: make(map[nativetypes.FieldIndex]bool, fieldCount), + dirtyIndices: make(map[nativetypes.FieldIndex][]uint64, fieldCount), + stateFieldLeaves: make(map[nativetypes.FieldIndex]*fieldtrie.FieldTrie, fieldCount), + sharedFieldReferences: make(map[nativetypes.FieldIndex]*stateutil.Reference, 11), + rebuildTrie: make(map[nativetypes.FieldIndex]bool, fieldCount), + valMapHandler: stateutil.NewValMapHandler(st.Validators), + } + + for _, f := range bellatrixFields { + b.dirtyFields[f] = true + b.rebuildTrie[f] = true + b.dirtyIndices[f] = []uint64{} + trie, err := fieldtrie.NewFieldTrie(f, types.BasicArray, nil, 0) + if err != nil { + return nil, err + } + b.stateFieldLeaves[f] = trie + } + + // Initialize field reference tracking for shared data. + b.sharedFieldReferences[nativetypes.BlockRoots] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.StateRoots] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.HistoricalRoots] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.Eth1DataVotes] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.Validators] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.Balances] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.RandaoMixes] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.Slashings] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.PreviousEpochParticipationBits] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.CurrentEpochParticipationBits] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.InactivityScores] = stateutil.NewRef(1) + b.sharedFieldReferences[nativetypes.LatestExecutionPayloadHeader] = stateutil.NewRef(1) // New in Bellatrix. + + state.StateCount.Inc() + return b, nil +} + +// Copy returns a deep copy of the beacon state. +func (b *BeaconState) Copy() state.BeaconState { + b.lock.RLock() + defer b.lock.RUnlock() + + var fieldCount int + switch b.version { + case version.Phase0: + fieldCount = params.BeaconConfig().BeaconStateFieldCount + case version.Altair: + fieldCount = params.BeaconConfig().BeaconStateAltairFieldCount + case version.Bellatrix: + fieldCount = params.BeaconConfig().BeaconStateBellatrixFieldCount + } + + dst := &BeaconState{ + version: b.version, + + // Primitive nativetypes, safe to copy. + genesisTime: b.genesisTime, + slot: b.slot, + eth1DepositIndex: b.eth1DepositIndex, + + // Large arrays, infrequently changed, constant size. + blockRoots: b.blockRoots, + stateRoots: b.stateRoots, + randaoMixes: b.randaoMixes, + previousEpochAttestations: b.previousEpochAttestations, + currentEpochAttestations: b.currentEpochAttestations, + eth1DataVotes: b.eth1DataVotes, + slashings: b.slashings, + + // Large arrays, increases over time. + balances: b.balances, + historicalRoots: b.historicalRoots, + validators: b.validators, + previousEpochParticipation: b.previousEpochParticipation, + currentEpochParticipation: b.currentEpochParticipation, + inactivityScores: b.inactivityScores, + + // Everything else, too small to be concerned about, constant size. + genesisValidatorsRoot: b.genesisValidatorsRoot, + justificationBits: b.justificationBitsVal(), + fork: b.forkVal(), + latestBlockHeader: b.latestBlockHeaderVal(), + eth1Data: b.eth1DataVal(), + previousJustifiedCheckpoint: b.previousJustifiedCheckpointVal(), + currentJustifiedCheckpoint: b.currentJustifiedCheckpointVal(), + finalizedCheckpoint: b.finalizedCheckpointVal(), + currentSyncCommittee: b.currentSyncCommitteeVal(), + nextSyncCommittee: b.nextSyncCommitteeVal(), + latestExecutionPayloadHeader: b.latestExecutionPayloadHeaderVal(), + + dirtyFields: make(map[nativetypes.FieldIndex]bool, fieldCount), + dirtyIndices: make(map[nativetypes.FieldIndex][]uint64, fieldCount), + rebuildTrie: make(map[nativetypes.FieldIndex]bool, fieldCount), + stateFieldLeaves: make(map[nativetypes.FieldIndex]*fieldtrie.FieldTrie, fieldCount), + + // Share the reference to validator index map. + valMapHandler: b.valMapHandler, + } + + switch b.version { + case version.Phase0: + dst.sharedFieldReferences = make(map[nativetypes.FieldIndex]*stateutil.Reference, 10) + case version.Altair: + dst.sharedFieldReferences = make(map[nativetypes.FieldIndex]*stateutil.Reference, 11) + case version.Bellatrix: + dst.sharedFieldReferences = make(map[nativetypes.FieldIndex]*stateutil.Reference, 11) + } + + for field, ref := range b.sharedFieldReferences { + ref.AddRef() + dst.sharedFieldReferences[field] = ref + } + + // Increment ref for validator map + b.valMapHandler.AddRef() + + for i := range b.dirtyFields { + dst.dirtyFields[i] = true + } + + for i := range b.dirtyIndices { + indices := make([]uint64, len(b.dirtyIndices[i])) + copy(indices, b.dirtyIndices[i]) + dst.dirtyIndices[i] = indices + } + + for i := range b.rebuildTrie { + dst.rebuildTrie[i] = true + } + + for fldIdx, fieldTrie := range b.stateFieldLeaves { + dst.stateFieldLeaves[fldIdx] = fieldTrie + if fieldTrie.FieldReference() != nil { + fieldTrie.Lock() + fieldTrie.FieldReference().AddRef() + fieldTrie.Unlock() + } + } + + if b.merkleLayers != nil { + dst.merkleLayers = make([][][]byte, len(b.merkleLayers)) + for i, layer := range b.merkleLayers { + dst.merkleLayers[i] = make([][]byte, len(layer)) + for j, content := range layer { + dst.merkleLayers[i][j] = make([]byte, len(content)) + copy(dst.merkleLayers[i][j], content) + } + } + } + + state.StateCount.Inc() + // Finalizer runs when dst is being destroyed in garbage collection. + runtime.SetFinalizer(dst, func(b *BeaconState) { + for field, v := range b.sharedFieldReferences { + v.MinusRef() + if b.stateFieldLeaves[field].FieldReference() != nil { + b.stateFieldLeaves[field].FieldReference().MinusRef() + } + + } + for i := range b.dirtyFields { + delete(b.dirtyFields, i) + } + for i := range b.rebuildTrie { + delete(b.rebuildTrie, i) + } + for i := range b.dirtyIndices { + delete(b.dirtyIndices, i) + } + for i := range b.sharedFieldReferences { + delete(b.sharedFieldReferences, i) + } + for i := range b.stateFieldLeaves { + delete(b.stateFieldLeaves, i) + } + state.StateCount.Sub(1) + }) + return dst +} + +// HashTreeRoot of the beacon state retrieves the Merkle root of the trie +// representation of the beacon state based on the Ethereum Simple Serialize specification. +func (b *BeaconState) HashTreeRoot(ctx context.Context) ([32]byte, error) { + ctx, span := trace.StartSpan(ctx, "beaconState.HashTreeRoot") + defer span.End() + + b.lock.Lock() + defer b.lock.Unlock() + if err := b.initializeMerkleLayers(ctx); err != nil { + return [32]byte{}, err + } + if err := b.recomputeDirtyFields(ctx); err != nil { + return [32]byte{}, err + } + return bytesutil.ToBytes32(b.merkleLayers[len(b.merkleLayers)-1][0]), nil +} + +// Initializes the Merkle layers for the beacon state if they are empty. +// WARNING: Caller must acquire the mutex before using. +func (b *BeaconState) initializeMerkleLayers(ctx context.Context) error { + if len(b.merkleLayers) > 0 { + return nil + } + fieldRoots, err := ComputeFieldRootsWithHasher(ctx, b) + if err != nil { + return err + } + layers := stateutil.Merkleize(fieldRoots) + b.merkleLayers = layers + switch b.version { + case version.Phase0: + b.dirtyFields = make(map[nativetypes.FieldIndex]bool, params.BeaconConfig().BeaconStateFieldCount) + case version.Altair: + b.dirtyFields = make(map[nativetypes.FieldIndex]bool, params.BeaconConfig().BeaconStateAltairFieldCount) + case version.Bellatrix: + b.dirtyFields = make(map[nativetypes.FieldIndex]bool, params.BeaconConfig().BeaconStateBellatrixFieldCount) + } + + return nil +} + +// Recomputes the Merkle layers for the dirty fields in the state. +// WARNING: Caller must acquire the mutex before using. +func (b *BeaconState) recomputeDirtyFields(ctx context.Context) error { + for field := range b.dirtyFields { + root, err := b.rootSelector(ctx, field) + if err != nil { + return err + } + idx := field.RealPosition() + b.merkleLayers[0][idx] = root[:] + b.recomputeRoot(idx) + delete(b.dirtyFields, field) + } + return nil +} + +// FieldReferencesCount returns the reference count held by each field. This +// also includes the field trie held by each field. +func (b *BeaconState) FieldReferencesCount() map[string]uint64 { + refMap := make(map[string]uint64) + b.lock.RLock() + defer b.lock.RUnlock() + for i, f := range b.sharedFieldReferences { + refMap[i.String(b.version)] = uint64(f.Refs()) + } + for i, f := range b.stateFieldLeaves { + numOfRefs := uint64(f.FieldReference().Refs()) + f.RLock() + if !f.Empty() { + refMap[i.String(b.version)+"_trie"] = numOfRefs + } + f.RUnlock() + } + return refMap +} + +// IsNil checks if the state and the underlying proto +// object are nil. +func (b *BeaconState) IsNil() bool { + return b == nil +} + +func (b *BeaconState) rootSelector(ctx context.Context, field nativetypes.FieldIndex) ([32]byte, error) { + _, span := trace.StartSpan(ctx, "beaconState.rootSelector") + defer span.End() + span.AddAttributes(trace.StringAttribute("field", field.String(b.version))) + + hasher := hash.CustomSHA256Hasher() + switch field { + case nativetypes.GenesisTime: + return ssz.Uint64Root(b.genesisTime), nil + case nativetypes.GenesisValidatorsRoot: + return b.genesisValidatorsRoot, nil + case nativetypes.Slot: + return ssz.Uint64Root(uint64(b.slot)), nil + case nativetypes.Eth1DepositIndex: + return ssz.Uint64Root(b.eth1DepositIndex), nil + case nativetypes.Fork: + return ssz.ForkRoot(b.fork) + case nativetypes.LatestBlockHeader: + return stateutil.BlockHeaderRoot(b.latestBlockHeader) + case nativetypes.BlockRoots: + if b.rebuildTrie[field] { + err := b.resetFieldTrie(field, b.blockRoots, fieldparams.BlockRootsLength) + if err != nil { + return [32]byte{}, err + } + delete(b.rebuildTrie, field) + return b.stateFieldLeaves[field].TrieRoot() + } + return b.recomputeFieldTrie(field, b.blockRoots) + case nativetypes.StateRoots: + if b.rebuildTrie[field] { + err := b.resetFieldTrie(field, b.stateRoots, fieldparams.StateRootsLength) + if err != nil { + return [32]byte{}, err + } + delete(b.rebuildTrie, field) + return b.stateFieldLeaves[field].TrieRoot() + } + return b.recomputeFieldTrie(field, b.stateRoots) + case nativetypes.HistoricalRoots: + hRoots := make([][]byte, len(b.historicalRoots)) + for i := range hRoots { + hRoots[i] = b.historicalRoots[i][:] + } + return ssz.ByteArrayRootWithLimit(hRoots, fieldparams.HistoricalRootsLength) + case nativetypes.Eth1Data: + return stateutil.Eth1Root(hasher, b.eth1Data) + case nativetypes.Eth1DataVotes: + if b.rebuildTrie[field] { + err := b.resetFieldTrie( + field, + b.eth1DataVotes, + fieldparams.Eth1DataVotesLength, + ) + if err != nil { + return [32]byte{}, err + } + delete(b.rebuildTrie, field) + return b.stateFieldLeaves[field].TrieRoot() + } + return b.recomputeFieldTrie(field, b.eth1DataVotes) + case nativetypes.Validators: + if b.rebuildTrie[field] { + err := b.resetFieldTrie(field, b.validators, fieldparams.ValidatorRegistryLimit) + if err != nil { + return [32]byte{}, err + } + delete(b.rebuildTrie, field) + return b.stateFieldLeaves[field].TrieRoot() + } + return b.recomputeFieldTrie(11, b.validators) + case nativetypes.Balances: + if b.rebuildTrie[field] { + maxBalCap := uint64(fieldparams.ValidatorRegistryLimit) + elemSize := uint64(8) + balLimit := (maxBalCap*elemSize + 31) / 32 + err := b.resetFieldTrie(field, b.balances, balLimit) + if err != nil { + return [32]byte{}, err + } + delete(b.rebuildTrie, field) + return b.stateFieldLeaves[field].TrieRoot() + } + return b.recomputeFieldTrie(12, b.balances) + case nativetypes.RandaoMixes: + if b.rebuildTrie[field] { + err := b.resetFieldTrie(field, b.randaoMixes, fieldparams.RandaoMixesLength) + if err != nil { + return [32]byte{}, err + } + delete(b.rebuildTrie, field) + return b.stateFieldLeaves[field].TrieRoot() + } + return b.recomputeFieldTrie(13, b.randaoMixes) + case nativetypes.Slashings: + return ssz.SlashingsRoot(b.slashings) + case nativetypes.PreviousEpochAttestations: + if b.rebuildTrie[field] { + err := b.resetFieldTrie( + field, + b.previousEpochAttestations, + fieldparams.PreviousEpochAttestationsLength, + ) + if err != nil { + return [32]byte{}, err + } + delete(b.rebuildTrie, field) + return b.stateFieldLeaves[field].TrieRoot() + } + return b.recomputeFieldTrie(field, b.previousEpochAttestations) + case nativetypes.CurrentEpochAttestations: + if b.rebuildTrie[field] { + err := b.resetFieldTrie( + field, + b.currentEpochAttestations, + fieldparams.CurrentEpochAttestationsLength, + ) + if err != nil { + return [32]byte{}, err + } + delete(b.rebuildTrie, field) + return b.stateFieldLeaves[field].TrieRoot() + } + return b.recomputeFieldTrie(field, b.currentEpochAttestations) + case nativetypes.PreviousEpochParticipationBits: + return stateutil.ParticipationBitsRoot(b.previousEpochParticipation) + case nativetypes.CurrentEpochParticipationBits: + return stateutil.ParticipationBitsRoot(b.currentEpochParticipation) + case nativetypes.JustificationBits: + return bytesutil.ToBytes32(b.justificationBits), nil + case nativetypes.PreviousJustifiedCheckpoint: + return ssz.CheckpointRoot(hasher, b.previousJustifiedCheckpoint) + case nativetypes.CurrentJustifiedCheckpoint: + return ssz.CheckpointRoot(hasher, b.currentJustifiedCheckpoint) + case nativetypes.FinalizedCheckpoint: + return ssz.CheckpointRoot(hasher, b.finalizedCheckpoint) + case nativetypes.InactivityScores: + return stateutil.Uint64ListRootWithRegistryLimit(b.inactivityScores) + case nativetypes.CurrentSyncCommittee: + return stateutil.SyncCommitteeRoot(b.currentSyncCommittee) + case nativetypes.NextSyncCommittee: + return stateutil.SyncCommitteeRoot(b.nextSyncCommittee) + case nativetypes.LatestExecutionPayloadHeader: + return b.latestExecutionPayloadHeader.HashTreeRoot() + } + return [32]byte{}, errors.New("invalid field index provided") +} + +func (b *BeaconState) recomputeFieldTrie(index nativetypes.FieldIndex, elements interface{}) ([32]byte, error) { + fTrie := b.stateFieldLeaves[index] + // We can't lock the trie directly because the trie's variable gets reassigned, + // and therefore we would call Unlock() on a different object. + fTrieMutex := fTrie.RWMutex + if fTrie.FieldReference().Refs() > 1 { + fTrieMutex.Lock() + fTrie.FieldReference().MinusRef() + newTrie := fTrie.CopyTrie() + b.stateFieldLeaves[index] = newTrie + fTrie = newTrie + fTrieMutex.Unlock() + } + // remove duplicate indexes + b.dirtyIndices[index] = slice.SetUint64(b.dirtyIndices[index]) + // sort indexes again + sort.Slice(b.dirtyIndices[index], func(i int, j int) bool { + return b.dirtyIndices[index][i] < b.dirtyIndices[index][j] + }) + root, err := fTrie.RecomputeTrie(b.dirtyIndices[index], elements) + if err != nil { + return [32]byte{}, err + } + b.dirtyIndices[index] = []uint64{} + return root, nil +} + +func (b *BeaconState) resetFieldTrie(index nativetypes.FieldIndex, elements interface{}, length uint64) error { + fTrie, err := fieldtrie.NewFieldTrie(index, fieldMap[index], elements, length) + if err != nil { + return err + } + b.stateFieldLeaves[index] = fTrie + b.dirtyIndices[index] = []uint64{} + return nil +} diff --git a/beacon-chain/state/state-native/v1/state_trie_test.go b/beacon-chain/state/state-native/state_trie_test.go similarity index 68% rename from beacon-chain/state/state-native/v1/state_trie_test.go rename to beacon-chain/state/state-native/state_trie_test.go index f365c913a0..ab23124ba4 100644 --- a/beacon-chain/state/state-native/v1/state_trie_test.go +++ b/beacon-chain/state/state-native/state_trie_test.go @@ -1,4 +1,4 @@ -package v1_test +package state_native_test import ( "bytes" @@ -6,7 +6,7 @@ import ( "testing" "github.com/prysmaticlabs/prysm/beacon-chain/state" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/v1" + statenative "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" @@ -15,9 +15,9 @@ import ( "github.com/prysmaticlabs/prysm/testing/util" ) -func TestInitializeFromProto(t *testing.T) { +func TestInitializeFromProto_Phase0(t *testing.T) { testState, _ := util.DeterministicGenesisState(t, 64) - pbState, err := v1.ProtobufBeaconState(testState.InnerStateUnsafe()) + pbState, err := statenative.ProtobufBeaconStatePhase0(testState.InnerStateUnsafe()) require.NoError(t, err) type test struct { name string @@ -48,7 +48,7 @@ func TestInitializeFromProto(t *testing.T) { } for _, tt := range initTests { t.Run(tt.name, func(t *testing.T) { - _, err := v1.InitializeFromProto(tt.state) + _, err := statenative.InitializeFromProtoUnsafePhase0(tt.state) if tt.error != "" { assert.ErrorContains(t, tt.error, err) } else { @@ -58,13 +58,10 @@ func TestInitializeFromProto(t *testing.T) { } } -func TestInitializeFromProtoUnsafe(t *testing.T) { - testState, _ := util.DeterministicGenesisState(t, 64) - pbState, err := v1.ProtobufBeaconState(testState.InnerStateUnsafe()) - require.NoError(t, err) +func TestInitializeFromProto_Altair(t *testing.T) { type test struct { name string - state *ethpb.BeaconState + state *ethpb.BeaconStateAltair error string } initTests := []test{ @@ -73,6 +70,77 @@ func TestInitializeFromProtoUnsafe(t *testing.T) { state: nil, error: "received nil state", }, + { + name: "nil validators", + state: ðpb.BeaconStateAltair{ + Slot: 4, + Validators: nil, + }, + }, + { + name: "empty state", + state: ðpb.BeaconStateAltair{}, + }, + // TODO: Add full state. Blocked by testutil migration. + } + for _, tt := range initTests { + t.Run(tt.name, func(t *testing.T) { + _, err := statenative.InitializeFromProtoAltair(tt.state) + if tt.error != "" { + require.ErrorContains(t, tt.error, err) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestInitializeFromProto_Bellatrix(t *testing.T) { + type test struct { + name string + state *ethpb.BeaconStateBellatrix + error string + } + initTests := []test{ + { + name: "nil state", + state: nil, + error: "received nil state", + }, + { + name: "nil validators", + state: ðpb.BeaconStateBellatrix{ + Slot: 4, + Validators: nil, + }, + }, + { + name: "empty state", + state: ðpb.BeaconStateBellatrix{}, + }, + } + for _, tt := range initTests { + t.Run(tt.name, func(t *testing.T) { + _, err := statenative.InitializeFromProtoBellatrix(tt.state) + if tt.error != "" { + require.ErrorContains(t, tt.error, err) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestInitializeFromProtoUnsafe_Phase0(t *testing.T) { + testState, _ := util.DeterministicGenesisState(t, 64) + pbState, err := statenative.ProtobufBeaconStatePhase0(testState.InnerStateUnsafe()) + require.NoError(t, err) + type test struct { + name string + state *ethpb.BeaconState + error string + } + initTests := []test{ { name: "nil validators", state: ðpb.BeaconState{ @@ -91,7 +159,7 @@ func TestInitializeFromProtoUnsafe(t *testing.T) { } for _, tt := range initTests { t.Run(tt.name, func(t *testing.T) { - _, err := v1.InitializeFromProtoUnsafe(tt.state) + _, err := statenative.InitializeFromProtoUnsafePhase0(tt.state) if tt.error != "" { assert.ErrorContains(t, tt.error, err) } else { @@ -101,6 +169,52 @@ func TestInitializeFromProtoUnsafe(t *testing.T) { } } +func TestInitializeFromProtoUnsafe_Altair(t *testing.T) { + type test struct { + name string + state *ethpb.BeaconStateAltair + error string + } + initTests := []test{ + { + name: "nil validators", + state: ðpb.BeaconStateAltair{ + Slot: 4, + Validators: nil, + }, + }, + { + name: "empty state", + state: ðpb.BeaconStateAltair{}, + }, + // TODO: Add full state. Blocked by testutil migration. + } + _ = initTests +} + +func TestInitializeFromProtoUnsafe_Bellatrix(t *testing.T) { + type test struct { + name string + state *ethpb.BeaconStateBellatrix + error string + } + initTests := []test{ + { + name: "nil validators", + state: ðpb.BeaconStateBellatrix{ + Slot: 4, + Validators: nil, + }, + }, + { + name: "empty state", + state: ðpb.BeaconStateBellatrix{}, + }, + // TODO: Add full state. Blocked by testutil migration. + } + _ = initTests +} + func TestBeaconState_HashTreeRoot(t *testing.T) { testState, _ := util.DeterministicGenesisState(t, 64) @@ -154,7 +268,7 @@ func TestBeaconState_HashTreeRoot(t *testing.T) { if err == nil && tt.error != "" { t.Errorf("Expected error, expected %v, recevied %v", tt.error, err) } - pbState, err := v1.ProtobufBeaconState(testState.InnerStateUnsafe()) + pbState, err := statenative.ProtobufBeaconStatePhase0(testState.InnerStateUnsafe()) require.NoError(t, err) genericHTR, err := pbState.HashTreeRoot() if err == nil && tt.error != "" { @@ -170,6 +284,24 @@ func TestBeaconState_HashTreeRoot(t *testing.T) { } } +func BenchmarkBeaconState(b *testing.B) { + testState, _ := util.DeterministicGenesisState(b, 16000) + pbState, err := statenative.ProtobufBeaconStatePhase0(testState.InnerStateUnsafe()) + require.NoError(b, err) + + b.Run("Vectorized SHA256", func(b *testing.B) { + st, err := statenative.InitializeFromProtoUnsafePhase0(pbState) + require.NoError(b, err) + _, err = st.HashTreeRoot(context.Background()) + assert.NoError(b, err) + }) + + b.Run("Current SHA256", func(b *testing.B) { + _, err := pbState.HashTreeRoot() + require.NoError(b, err) + }) +} + func TestBeaconState_HashTreeRoot_FieldTrie(t *testing.T) { testState, _ := util.DeterministicGenesisState(t, 64) @@ -223,7 +355,7 @@ func TestBeaconState_HashTreeRoot_FieldTrie(t *testing.T) { if err == nil && tt.error != "" { t.Errorf("Expected error, expected %v, recevied %v", tt.error, err) } - pbState, err := v1.ProtobufBeaconState(testState.InnerStateUnsafe()) + pbState, err := statenative.ProtobufBeaconStatePhase0(testState.InnerStateUnsafe()) require.NoError(t, err) genericHTR, err := pbState.HashTreeRoot() if err == nil && tt.error != "" { @@ -251,21 +383,3 @@ func TestBeaconState_AppendValidator_DoesntMutateCopy(t *testing.T) { _, ok := st1.ValidatorIndexByPubkey(bytesutil.ToBytes48(val.PublicKey)) assert.Equal(t, false, ok, "Expected no validator index to be present in st1 for the newly inserted pubkey") } - -func BenchmarkBeaconState(b *testing.B) { - testState, _ := util.DeterministicGenesisState(b, 16000) - pbState, err := v1.ProtobufBeaconState(testState.InnerStateUnsafe()) - require.NoError(b, err) - - b.Run("Vectorized SHA256", func(b *testing.B) { - st, err := v1.InitializeFromProtoUnsafe(pbState) - require.NoError(b, err) - _, err = st.HashTreeRoot(context.Background()) - assert.NoError(b, err) - }) - - b.Run("Current SHA256", func(b *testing.B) { - _, err := pbState.HashTreeRoot() - require.NoError(b, err) - }) -} diff --git a/beacon-chain/state/state-native/types.go b/beacon-chain/state/state-native/types.go new file mode 100644 index 0000000000..da3cf25f52 --- /dev/null +++ b/beacon-chain/state/state-native/types.go @@ -0,0 +1,36 @@ +package state_native + +import ( + "fmt" + + "github.com/prysmaticlabs/prysm/beacon-chain/state" + nativetypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/types" + "github.com/prysmaticlabs/prysm/beacon-chain/state/types" + "github.com/prysmaticlabs/prysm/runtime/version" +) + +// Ensure type BeaconState below implements BeaconState interface. +var _ state.BeaconState = (*BeaconState)(nil) + +func init() { + fieldMap = make(map[nativetypes.FieldIndex]types.DataType) + // Initialize the fixed sized arrays. + fieldMap[nativetypes.BlockRoots] = types.BasicArray + fieldMap[nativetypes.StateRoots] = types.BasicArray + fieldMap[nativetypes.RandaoMixes] = types.BasicArray + + // Initialize the composite arrays. + fieldMap[nativetypes.Eth1DataVotes] = types.CompositeArray + fieldMap[nativetypes.Validators] = types.CompositeArray + fieldMap[nativetypes.PreviousEpochAttestations] = types.CompositeArray + fieldMap[nativetypes.CurrentEpochAttestations] = types.CompositeArray + fieldMap[nativetypes.Balances] = types.CompressedArray +} + +// fieldMap keeps track of each field +// to its corresponding data type. +var fieldMap map[nativetypes.FieldIndex]types.DataType + +func errNotSupported(funcName string, ver int) error { + return fmt.Errorf("%s is not supported for %s", funcName, version.String(ver)) +} diff --git a/beacon-chain/state/state-native/types/BUILD.bazel b/beacon-chain/state/state-native/types/BUILD.bazel new file mode 100644 index 0000000000..b5a3d8c4b8 --- /dev/null +++ b/beacon-chain/state/state-native/types/BUILD.bazel @@ -0,0 +1,9 @@ +load("@prysm//tools/go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["types.go"], + importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/types", + visibility = ["//visibility:public"], + deps = ["@com_github_pkg_errors//:go_default_library"], +) diff --git a/beacon-chain/state/state-native/types/types.go b/beacon-chain/state/state-native/types/types.go new file mode 100644 index 0000000000..2c507455ac --- /dev/null +++ b/beacon-chain/state/state-native/types/types.go @@ -0,0 +1,181 @@ +package types + +import ( + "github.com/pkg/errors" +) + +// FieldIndex represents the relevant field position in the +// state struct for a field. +type FieldIndex int + +// String returns the name of the field index. +func (f FieldIndex) String(_ int) string { + switch f { + case GenesisTime: + return "genesisTime" + case GenesisValidatorsRoot: + return "genesisValidatorsRoot" + case Slot: + return "slot" + case Fork: + return "fork" + case LatestBlockHeader: + return "latestBlockHeader" + case BlockRoots: + return "blockRoots" + case StateRoots: + return "stateRoots" + case HistoricalRoots: + return "historicalRoots" + case Eth1Data: + return "eth1Data" + case Eth1DataVotes: + return "eth1DataVotes" + case Eth1DepositIndex: + return "eth1DepositIndex" + case Validators: + return "validators" + case Balances: + return "balances" + case RandaoMixes: + return "randaoMixes" + case Slashings: + return "slashings" + case PreviousEpochAttestations: + return "previousEpochAttestations" + case CurrentEpochAttestations: + return "currentEpochAttestations" + case PreviousEpochParticipationBits: + return "previousEpochParticipationBits" + case CurrentEpochParticipationBits: + return "currentEpochParticipationBits" + case JustificationBits: + return "justificationBits" + case PreviousJustifiedCheckpoint: + return "previousJustifiedCheckpoint" + case CurrentJustifiedCheckpoint: + return "currentJustifiedCheckpoint" + case FinalizedCheckpoint: + return "finalizedCheckpoint" + case InactivityScores: + return "inactivityScores" + case CurrentSyncCommittee: + return "currentSyncCommittee" + case NextSyncCommittee: + return "nextSyncCommittee" + case LatestExecutionPayloadHeader: + return "latestExecutionPayloadHeader" + default: + return "" + } +} + +// RealPosition denotes the position of the field in the beacon state. +// The value might differ for different state versions. +func (f FieldIndex) RealPosition() int { + switch f { + case GenesisTime: + return 0 + case GenesisValidatorsRoot: + return 1 + case Slot: + return 2 + case Fork: + return 3 + case LatestBlockHeader: + return 4 + case BlockRoots: + return 5 + case StateRoots: + return 6 + case HistoricalRoots: + return 7 + case Eth1Data: + return 8 + case Eth1DataVotes: + return 9 + case Eth1DepositIndex: + return 10 + case Validators: + return 11 + case Balances: + return 12 + case RandaoMixes: + return 13 + case Slashings: + return 14 + case PreviousEpochAttestations, PreviousEpochParticipationBits: + return 15 + case CurrentEpochAttestations, CurrentEpochParticipationBits: + return 16 + case JustificationBits: + return 17 + case PreviousJustifiedCheckpoint: + return 18 + case CurrentJustifiedCheckpoint: + return 19 + case FinalizedCheckpoint: + return 20 + case InactivityScores: + return 21 + case CurrentSyncCommittee: + return 22 + case NextSyncCommittee: + return 23 + case LatestExecutionPayloadHeader: + return 24 + default: + return -1 + } +} + +// ElemsInChunk returns the number of elements in the chunk (number of +// elements that are able to be packed). +func (f FieldIndex) ElemsInChunk() (uint64, error) { + switch f { + case Balances: + return 4, nil + default: + return 0, errors.Errorf("field %d doesn't support element compression", f) + } +} + +func (FieldIndex) Native() bool { + return true +} + +// Below we define a set of useful enum values for the field +// indices of the beacon state. For example, genesisTime is the +// 0th field of the beacon state. This is helpful when we are +// updating the Merkle branches up the trie representation +// of the beacon state. The below field indexes correspond +// to the state. +const ( + GenesisTime FieldIndex = iota + GenesisValidatorsRoot + Slot + Fork + LatestBlockHeader + BlockRoots + StateRoots + HistoricalRoots + Eth1Data + Eth1DataVotes + Eth1DepositIndex + Validators + Balances + RandaoMixes + Slashings + PreviousEpochAttestations + CurrentEpochAttestations + PreviousEpochParticipationBits + CurrentEpochParticipationBits + JustificationBits + PreviousJustifiedCheckpoint + CurrentJustifiedCheckpoint + FinalizedCheckpoint + InactivityScores + CurrentSyncCommittee + NextSyncCommittee + LatestExecutionPayloadHeader +) diff --git a/beacon-chain/state/state-native/v1/types_test.go b/beacon-chain/state/state-native/types_test.go similarity index 92% rename from beacon-chain/state/state-native/v1/types_test.go rename to beacon-chain/state/state-native/types_test.go index 225780aa27..80188b1151 100644 --- a/beacon-chain/state/state-native/v1/types_test.go +++ b/beacon-chain/state/state-native/types_test.go @@ -1,4 +1,4 @@ -package v1_test +package state_native_test import ( "context" @@ -6,7 +6,7 @@ import ( "strconv" "testing" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/v1" + statenative "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/encoding/bytesutil" @@ -20,14 +20,9 @@ import ( func TestBeaconState_ProtoBeaconStateCompatibility(t *testing.T) { params.SetupTestConfigCleanup(t) - cfg := params.MinimalSpecConfig() - cfg.SlotsPerHistoricalRoot = fieldparams.BlockRootsLength - cfg.EpochsPerHistoricalVector = fieldparams.RandaoMixesLength - params.OverrideBeaconConfig(cfg) - ctx := context.Background() genesis := setupGenesisState(t, 64) - customState, err := v1.InitializeFromProto(genesis) + customState, err := statenative.InitializeFromProtoPhase0(genesis) require.NoError(t, err) cloned, ok := proto.Clone(genesis).(*ethpb.BeaconState) assert.Equal(t, true, ok, "Object is not of type *ethpb.BeaconState") @@ -36,7 +31,7 @@ func TestBeaconState_ProtoBeaconStateCompatibility(t *testing.T) { r1, err := customState.HashTreeRoot(ctx) require.NoError(t, err) - beaconState, err := v1.InitializeFromProto(genesis) + beaconState, err := statenative.InitializeFromProtoPhase0(genesis) require.NoError(t, err) r2, err := beaconState.HashTreeRoot(context.Background()) require.NoError(t, err) @@ -49,7 +44,7 @@ func TestBeaconState_ProtoBeaconStateCompatibility(t *testing.T) { r1, err = customState.HashTreeRoot(ctx) require.NoError(t, err) genesis.Balances = balances - beaconState, err = v1.InitializeFromProto(genesis) + beaconState, err = statenative.InitializeFromProtoPhase0(genesis) require.NoError(t, err) r2, err = beaconState.HashTreeRoot(context.Background()) require.NoError(t, err) @@ -142,7 +137,7 @@ func BenchmarkStateClone_Manual(b *testing.B) { params.SetupTestConfigCleanup(b) params.OverrideBeaconConfig(params.MinimalSpecConfig()) genesis := setupGenesisState(b, 64) - st, err := v1.InitializeFromProto(genesis) + st, err := statenative.InitializeFromProtoPhase0(genesis) require.NoError(b, err) b.StartTimer() for i := 0; i < b.N; i++ { @@ -184,7 +179,7 @@ func TestBeaconState_ImmutabilityWithSharedResources(t *testing.T) { params.SetupTestConfigCleanup(t) params.OverrideBeaconConfig(params.MinimalSpecConfig()) genesis := setupGenesisState(t, 64) - a, err := v1.InitializeFromProto(genesis) + a, err := statenative.InitializeFromProtoPhase0(genesis) require.NoError(t, err) b := a.Copy() @@ -221,7 +216,7 @@ func TestForkManualCopy_OK(t *testing.T) { params.SetupTestConfigCleanup(t) params.OverrideBeaconConfig(params.MinimalSpecConfig()) genesis := setupGenesisState(t, 64) - a, err := v1.InitializeFromProto(genesis) + a, err := statenative.InitializeFromProtoPhase0(genesis) require.NoError(t, err) wantedFork := ðpb.Fork{ PreviousVersion: []byte{'a', 'b', 'c'}, @@ -230,7 +225,7 @@ func TestForkManualCopy_OK(t *testing.T) { } require.NoError(t, a.SetFork(wantedFork)) - pbState, err := v1.ProtobufBeaconState(a.InnerStateUnsafe()) + pbState, err := statenative.ProtobufBeaconStatePhase0(a.InnerStateUnsafe()) require.NoError(t, err) require.DeepEqual(t, pbState.Fork, wantedFork) } diff --git a/beacon-chain/state/state-native/v1/beacon_state_mainnet.go b/beacon-chain/state/state-native/v1/beacon_state_mainnet.go deleted file mode 100644 index 91d0d34538..0000000000 --- a/beacon-chain/state/state-native/v1/beacon_state_mainnet.go +++ /dev/null @@ -1,51 +0,0 @@ -//go:build !minimal -// +build !minimal - -package v1 - -import ( - "sync" - - "github.com/prysmaticlabs/go-bitfield" - "github.com/prysmaticlabs/prysm/beacon-chain/state/fieldtrie" - customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - "github.com/prysmaticlabs/prysm/beacon-chain/state/types" - eth2types "github.com/prysmaticlabs/prysm/consensus-types/primitives" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -// BeaconState defines a struct containing utilities for the Ethereum Beacon Chain state, defining -// getters and setters for its respective values and helpful functions such as HashTreeRoot(). -type BeaconState struct { - genesisTime uint64 `ssz-gen:"true"` - genesisValidatorsRoot customtypes.Byte32 `ssz-gen:"true" ssz-size:"32"` - slot eth2types.Slot `ssz-gen:"true"` - fork *ethpb.Fork `ssz-gen:"true"` - latestBlockHeader *ethpb.BeaconBlockHeader `ssz-gen:"true"` - blockRoots *customtypes.BlockRoots `ssz-gen:"true" ssz-size:"8192,32"` - stateRoots *customtypes.StateRoots `ssz-gen:"true" ssz-size:"8192,32"` - historicalRoots customtypes.HistoricalRoots `ssz-gen:"true" ssz-size:"?,32" ssz-max:"16777216"` - eth1Data *ethpb.Eth1Data `ssz-gen:"true"` - eth1DataVotes []*ethpb.Eth1Data `ssz-gen:"true" ssz-max:"2048"` - eth1DepositIndex uint64 `ssz-gen:"true"` - validators []*ethpb.Validator `ssz-gen:"true" ssz-max:"1099511627776"` - balances []uint64 `ssz-gen:"true" ssz-max:"1099511627776"` - randaoMixes *customtypes.RandaoMixes `ssz-gen:"true" ssz-size:"65536,32"` - slashings []uint64 `ssz-gen:"true" ssz-size:"8192"` - previousEpochAttestations []*ethpb.PendingAttestation `ssz-gen:"true" ssz-max:"4096"` - currentEpochAttestations []*ethpb.PendingAttestation `ssz-gen:"true" ssz-max:"4096"` - justificationBits bitfield.Bitvector4 `ssz-gen:"true" ssz-size:"1"` - previousJustifiedCheckpoint *ethpb.Checkpoint `ssz-gen:"true"` - currentJustifiedCheckpoint *ethpb.Checkpoint `ssz-gen:"true"` - finalizedCheckpoint *ethpb.Checkpoint `ssz-gen:"true"` - - lock sync.RWMutex - dirtyFields map[types.FieldIndex]bool - dirtyIndices map[types.FieldIndex][]uint64 - stateFieldLeaves map[types.FieldIndex]*fieldtrie.FieldTrie - rebuildTrie map[types.FieldIndex]bool - valMapHandler *stateutil.ValidatorMapHandler - merkleLayers [][][]byte - sharedFieldReferences map[types.FieldIndex]*stateutil.Reference -} diff --git a/beacon-chain/state/state-native/v1/beacon_state_minimal.go b/beacon-chain/state/state-native/v1/beacon_state_minimal.go deleted file mode 100644 index 55546171a5..0000000000 --- a/beacon-chain/state/state-native/v1/beacon_state_minimal.go +++ /dev/null @@ -1,51 +0,0 @@ -//go:build minimal -// +build minimal - -package v1 - -import ( - "sync" - - "github.com/prysmaticlabs/go-bitfield" - "github.com/prysmaticlabs/prysm/beacon-chain/state/fieldtrie" - customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - "github.com/prysmaticlabs/prysm/beacon-chain/state/types" - eth2types "github.com/prysmaticlabs/prysm/consensus-types/primitives" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -// BeaconState defines a struct containing utilities for the Ethereum Beacon Chain state, defining -// getters and setters for its respective values and helpful functions such as HashTreeRoot(). -type BeaconState struct { - genesisTime uint64 `ssz-gen:"true"` - genesisValidatorsRoot customtypes.Byte32 `ssz-gen:"true" ssz-size:"32"` - slot eth2types.Slot `ssz-gen:"true"` - fork *ethpb.Fork `ssz-gen:"true"` - latestBlockHeader *ethpb.BeaconBlockHeader `ssz-gen:"true"` - blockRoots *customtypes.BlockRoots `ssz-gen:"true" ssz-size:"64,32"` - stateRoots *customtypes.StateRoots `ssz-gen:"true" ssz-size:"64,32"` - historicalRoots customtypes.HistoricalRoots `ssz-gen:"true" ssz-size:"?,32" ssz-max:"16777216"` - eth1Data *ethpb.Eth1Data `ssz-gen:"true"` - eth1DataVotes []*ethpb.Eth1Data `ssz-gen:"true" ssz-max:"32"` - eth1DepositIndex uint64 `ssz-gen:"true"` - validators []*ethpb.Validator `ssz-gen:"true" ssz-max:"1099511627776"` - balances []uint64 `ssz-gen:"true" ssz-max:"1099511627776"` - randaoMixes *customtypes.RandaoMixes `ssz-gen:"true" ssz-size:"64,32"` - slashings []uint64 `ssz-gen:"true" ssz-size:"64"` - previousEpochAttestations []*ethpb.PendingAttestation `ssz-gen:"true" ssz-max:"1024"` - currentEpochAttestations []*ethpb.PendingAttestation `ssz-gen:"true" ssz-max:"1024"` - justificationBits bitfield.Bitvector4 `ssz-gen:"true" ssz-size:"1"` - previousJustifiedCheckpoint *ethpb.Checkpoint `ssz-gen:"true"` - currentJustifiedCheckpoint *ethpb.Checkpoint `ssz-gen:"true"` - finalizedCheckpoint *ethpb.Checkpoint `ssz-gen:"true"` - - lock sync.RWMutex - dirtyFields map[types.FieldIndex]bool - dirtyIndices map[types.FieldIndex][]uint64 - stateFieldLeaves map[types.FieldIndex]*fieldtrie.FieldTrie - rebuildTrie map[types.FieldIndex]bool - valMapHandler *stateutil.ValidatorMapHandler - merkleLayers [][][]byte - sharedFieldReferences map[types.FieldIndex]*stateutil.Reference -} diff --git a/beacon-chain/state/state-native/v1/field_roots.go b/beacon-chain/state/state-native/v1/field_roots.go deleted file mode 100644 index 0aa5725a0a..0000000000 --- a/beacon-chain/state/state-native/v1/field_roots.go +++ /dev/null @@ -1,14 +0,0 @@ -package v1 - -import ( - "context" - - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -// computeFieldRoots returns the hash tree root computations of every field in -// the beacon state as a list of 32 byte roots. -func computeFieldRoots(ctx context.Context, state *ethpb.BeaconState) ([][]byte, error) { - return stateutil.ComputeFieldRootsWithHasherPhase0(ctx, state) -} diff --git a/beacon-chain/state/state-native/v1/generated.ssz.go b/beacon-chain/state/state-native/v1/generated.ssz.go deleted file mode 100644 index 6c41772f44..0000000000 --- a/beacon-chain/state/state-native/v1/generated.ssz.go +++ /dev/null @@ -1,493 +0,0 @@ -// Code generated by fastssz. DO NOT EDIT. -// Hash: fcd8a2db8c7071e198d2acf714243a3f8875b92cdc1a3a085134db7c47f01ce6 -package v1 - -import ( - ssz "github.com/ferranbt/fastssz" - eth2types "github.com/prysmaticlabs/prysm/consensus-types/primitives" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -// MarshalSSZ ssz marshals the BeaconState object -func (b *BeaconState) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(b) -} - -// MarshalSSZTo ssz marshals the BeaconState object to a target array -func (b *BeaconState) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - offset := int(2687377) - - // Field (0) 'genesisTime' - dst = ssz.MarshalUint64(dst, b.genesisTime) - - // Field (1) 'genesisValidatorsRoot' - dst = append(dst, b.genesisValidatorsRoot[:]...) - - // Field (2) 'slot' - dst = ssz.MarshalUint64(dst, uint64(b.slot)) - - // Field (3) 'fork' - if b.fork == nil { - b.fork = new(ethpb.Fork) - } - if dst, err = b.fork.MarshalSSZTo(dst); err != nil { - return - } - - // Field (4) 'latestBlockHeader' - if b.latestBlockHeader == nil { - b.latestBlockHeader = new(ethpb.BeaconBlockHeader) - } - if dst, err = b.latestBlockHeader.MarshalSSZTo(dst); err != nil { - return - } - - // Field (5) 'blockRoots' - for ii := 0; ii < 8192; ii++ { - dst = append(dst, b.blockRoots[ii][:]...) - } - - // Field (6) 'stateRoots' - for ii := 0; ii < 8192; ii++ { - dst = append(dst, b.stateRoots[ii][:]...) - } - - // Offset (7) 'historicalRoots' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.historicalRoots) * 32 - - // Field (8) 'eth1Data' - if b.eth1Data == nil { - b.eth1Data = new(ethpb.Eth1Data) - } - if dst, err = b.eth1Data.MarshalSSZTo(dst); err != nil { - return - } - - // Offset (9) 'eth1DataVotes' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.eth1DataVotes) * 72 - - // Field (10) 'eth1DepositIndex' - dst = ssz.MarshalUint64(dst, b.eth1DepositIndex) - - // Offset (11) 'validators' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.validators) * 121 - - // Offset (12) 'balances' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.balances) * 8 - - // Field (13) 'randaoMixes' - for ii := 0; ii < 65536; ii++ { - dst = append(dst, b.randaoMixes[ii][:]...) - } - - // Field (14) 'slashings' - if len(b.slashings) != 8192 { - err = ssz.ErrVectorLength - return - } - for ii := 0; ii < 8192; ii++ { - dst = ssz.MarshalUint64(dst, b.slashings[ii]) - } - - // Offset (15) 'previousEpochAttestations' - dst = ssz.WriteOffset(dst, offset) - for ii := 0; ii < len(b.previousEpochAttestations); ii++ { - offset += 4 - offset += b.previousEpochAttestations[ii].SizeSSZ() - } - - // Offset (16) 'currentEpochAttestations' - dst = ssz.WriteOffset(dst, offset) - for ii := 0; ii < len(b.currentEpochAttestations); ii++ { - offset += 4 - offset += b.currentEpochAttestations[ii].SizeSSZ() - } - - // Field (17) 'justificationBits' - if len(b.justificationBits) != 1 { - err = ssz.ErrBytesLength - return - } - dst = append(dst, b.justificationBits...) - - // Field (18) 'previousJustifiedCheckpoint' - if b.previousJustifiedCheckpoint == nil { - b.previousJustifiedCheckpoint = new(ethpb.Checkpoint) - } - if dst, err = b.previousJustifiedCheckpoint.MarshalSSZTo(dst); err != nil { - return - } - - // Field (19) 'currentJustifiedCheckpoint' - if b.currentJustifiedCheckpoint == nil { - b.currentJustifiedCheckpoint = new(ethpb.Checkpoint) - } - if dst, err = b.currentJustifiedCheckpoint.MarshalSSZTo(dst); err != nil { - return - } - - // Field (20) 'finalizedCheckpoint' - if b.finalizedCheckpoint == nil { - b.finalizedCheckpoint = new(ethpb.Checkpoint) - } - if dst, err = b.finalizedCheckpoint.MarshalSSZTo(dst); err != nil { - return - } - - // Field (7) 'historicalRoots' - if len(b.historicalRoots) > 16777216 { - err = ssz.ErrListTooBig - return - } - for ii := 0; ii < len(b.historicalRoots); ii++ { - dst = append(dst, b.historicalRoots[ii][:]...) - } - - // Field (9) 'eth1DataVotes' - if len(b.eth1DataVotes) > 2048 { - err = ssz.ErrListTooBig - return - } - for ii := 0; ii < len(b.eth1DataVotes); ii++ { - if dst, err = b.eth1DataVotes[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (11) 'validators' - if len(b.validators) > 1099511627776 { - err = ssz.ErrListTooBig - return - } - for ii := 0; ii < len(b.validators); ii++ { - if dst, err = b.validators[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (12) 'balances' - if len(b.balances) > 1099511627776 { - err = ssz.ErrListTooBig - return - } - for ii := 0; ii < len(b.balances); ii++ { - dst = ssz.MarshalUint64(dst, b.balances[ii]) - } - - // Field (15) 'previousEpochAttestations' - if len(b.previousEpochAttestations) > 4096 { - err = ssz.ErrListTooBig - return - } - { - offset = 4 * len(b.previousEpochAttestations) - for ii := 0; ii < len(b.previousEpochAttestations); ii++ { - dst = ssz.WriteOffset(dst, offset) - offset += b.previousEpochAttestations[ii].SizeSSZ() - } - } - for ii := 0; ii < len(b.previousEpochAttestations); ii++ { - if dst, err = b.previousEpochAttestations[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (16) 'currentEpochAttestations' - if len(b.currentEpochAttestations) > 4096 { - err = ssz.ErrListTooBig - return - } - { - offset = 4 * len(b.currentEpochAttestations) - for ii := 0; ii < len(b.currentEpochAttestations); ii++ { - dst = ssz.WriteOffset(dst, offset) - offset += b.currentEpochAttestations[ii].SizeSSZ() - } - } - for ii := 0; ii < len(b.currentEpochAttestations); ii++ { - if dst, err = b.currentEpochAttestations[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - return -} - -// UnmarshalSSZ ssz unmarshals the BeaconState object -func (b *BeaconState) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size < 2687377 { - return ssz.ErrSize - } - - tail := buf - var o7, o9, o11, o12, o15, o16 uint64 - - // Field (0) 'genesisTime' - b.genesisTime = ssz.UnmarshallUint64(buf[0:8]) - - // Field (1) 'genesisValidatorsRoot' - copy(b.genesisValidatorsRoot[:], buf[8:40]) - - // Field (2) 'slot' - b.slot = eth2types.Slot(ssz.UnmarshallUint64(buf[40:48])) - - // Field (3) 'fork' - if b.fork == nil { - b.fork = new(ethpb.Fork) - } - if err = b.fork.UnmarshalSSZ(buf[48:64]); err != nil { - return err - } - - // Field (4) 'latestBlockHeader' - if b.latestBlockHeader == nil { - b.latestBlockHeader = new(ethpb.BeaconBlockHeader) - } - if err = b.latestBlockHeader.UnmarshalSSZ(buf[64:176]); err != nil { - return err - } - - // Field (5) 'blockRoots' - - for ii := 0; ii < 8192; ii++ { - copy(b.blockRoots[ii][:], buf[176:262320][ii*32:(ii+1)*32]) - } - - // Field (6) 'stateRoots' - - for ii := 0; ii < 8192; ii++ { - copy(b.stateRoots[ii][:], buf[262320:524464][ii*32:(ii+1)*32]) - } - - // Offset (7) 'historicalRoots' - if o7 = ssz.ReadOffset(buf[524464:524468]); o7 > size { - return ssz.ErrOffset - } - - if o7 < 2687377 { - return ssz.ErrInvalidVariableOffset - } - - // Field (8) 'eth1Data' - if b.eth1Data == nil { - b.eth1Data = new(ethpb.Eth1Data) - } - if err = b.eth1Data.UnmarshalSSZ(buf[524468:524540]); err != nil { - return err - } - - // Offset (9) 'eth1DataVotes' - if o9 = ssz.ReadOffset(buf[524540:524544]); o9 > size || o7 > o9 { - return ssz.ErrOffset - } - - // Field (10) 'eth1DepositIndex' - b.eth1DepositIndex = ssz.UnmarshallUint64(buf[524544:524552]) - - // Offset (11) 'validators' - if o11 = ssz.ReadOffset(buf[524552:524556]); o11 > size || o9 > o11 { - return ssz.ErrOffset - } - - // Offset (12) 'balances' - if o12 = ssz.ReadOffset(buf[524556:524560]); o12 > size || o11 > o12 { - return ssz.ErrOffset - } - - // Field (13) 'randaoMixes' - - for ii := 0; ii < 65536; ii++ { - copy(b.randaoMixes[ii][:], buf[524560:2621712][ii*32:(ii+1)*32]) - } - - // Field (14) 'slashings' - b.slashings = ssz.ExtendUint64(b.slashings, 8192) - for ii := 0; ii < 8192; ii++ { - b.slashings[ii] = ssz.UnmarshallUint64(buf[2621712:2687248][ii*8 : (ii+1)*8]) - } - - // Offset (15) 'previousEpochAttestations' - if o15 = ssz.ReadOffset(buf[2687248:2687252]); o15 > size || o12 > o15 { - return ssz.ErrOffset - } - - // Offset (16) 'currentEpochAttestations' - if o16 = ssz.ReadOffset(buf[2687252:2687256]); o16 > size || o15 > o16 { - return ssz.ErrOffset - } - - // Field (17) 'justificationBits' - if cap(b.justificationBits) == 0 { - b.justificationBits = make([]byte, 0, len(buf[2687256:2687257])) - } - b.justificationBits = append(b.justificationBits, buf[2687256:2687257]...) - - // Field (18) 'previousJustifiedCheckpoint' - if b.previousJustifiedCheckpoint == nil { - b.previousJustifiedCheckpoint = new(ethpb.Checkpoint) - } - if err = b.previousJustifiedCheckpoint.UnmarshalSSZ(buf[2687257:2687297]); err != nil { - return err - } - - // Field (19) 'currentJustifiedCheckpoint' - if b.currentJustifiedCheckpoint == nil { - b.currentJustifiedCheckpoint = new(ethpb.Checkpoint) - } - if err = b.currentJustifiedCheckpoint.UnmarshalSSZ(buf[2687297:2687337]); err != nil { - return err - } - - // Field (20) 'finalizedCheckpoint' - if b.finalizedCheckpoint == nil { - b.finalizedCheckpoint = new(ethpb.Checkpoint) - } - if err = b.finalizedCheckpoint.UnmarshalSSZ(buf[2687337:2687377]); err != nil { - return err - } - - // Field (7) 'historicalRoots' - { - buf = tail[o7:o9] - num, err := ssz.DivideInt2(len(buf), 32, 16777216) - if err != nil { - return err - } - b.historicalRoots = make([][32]byte, num) - for ii := 0; ii < num; ii++ { - copy(b.historicalRoots[ii][:], buf[ii*32:(ii+1)*32]) - } - } - - // Field (9) 'eth1DataVotes' - { - buf = tail[o9:o11] - num, err := ssz.DivideInt2(len(buf), 72, 2048) - if err != nil { - return err - } - b.eth1DataVotes = make([]*ethpb.Eth1Data, num) - for ii := 0; ii < num; ii++ { - if b.eth1DataVotes[ii] == nil { - b.eth1DataVotes[ii] = new(ethpb.Eth1Data) - } - if err = b.eth1DataVotes[ii].UnmarshalSSZ(buf[ii*72 : (ii+1)*72]); err != nil { - return err - } - } - } - - // Field (11) 'validators' - { - buf = tail[o11:o12] - num, err := ssz.DivideInt2(len(buf), 121, 1099511627776) - if err != nil { - return err - } - b.validators = make([]*ethpb.Validator, num) - for ii := 0; ii < num; ii++ { - if b.validators[ii] == nil { - b.validators[ii] = new(ethpb.Validator) - } - if err = b.validators[ii].UnmarshalSSZ(buf[ii*121 : (ii+1)*121]); err != nil { - return err - } - } - } - - // Field (12) 'balances' - { - buf = tail[o12:o15] - num, err := ssz.DivideInt2(len(buf), 8, 1099511627776) - if err != nil { - return err - } - b.balances = ssz.ExtendUint64(b.balances, num) - for ii := 0; ii < num; ii++ { - b.balances[ii] = ssz.UnmarshallUint64(buf[ii*8 : (ii+1)*8]) - } - } - - // Field (15) 'previousEpochAttestations' - { - buf = tail[o15:o16] - num, err := ssz.DecodeDynamicLength(buf, 4096) - if err != nil { - return err - } - b.previousEpochAttestations = make([]*ethpb.PendingAttestation, num) - err = ssz.UnmarshalDynamic(buf, num, func(indx int, buf []byte) (err error) { - if b.previousEpochAttestations[indx] == nil { - b.previousEpochAttestations[indx] = new(ethpb.PendingAttestation) - } - if err = b.previousEpochAttestations[indx].UnmarshalSSZ(buf); err != nil { - return err - } - return nil - }) - if err != nil { - return err - } - } - - // Field (16) 'currentEpochAttestations' - { - buf = tail[o16:] - num, err := ssz.DecodeDynamicLength(buf, 4096) - if err != nil { - return err - } - b.currentEpochAttestations = make([]*ethpb.PendingAttestation, num) - err = ssz.UnmarshalDynamic(buf, num, func(indx int, buf []byte) (err error) { - if b.currentEpochAttestations[indx] == nil { - b.currentEpochAttestations[indx] = new(ethpb.PendingAttestation) - } - if err = b.currentEpochAttestations[indx].UnmarshalSSZ(buf); err != nil { - return err - } - return nil - }) - if err != nil { - return err - } - } - return err -} - -// SizeSSZ returns the ssz encoded size in bytes for the BeaconState object -func (b *BeaconState) SizeSSZ() (size int) { - size = 2687377 - - // Field (7) 'historicalRoots' - size += len(b.historicalRoots) * 32 - - // Field (9) 'eth1DataVotes' - size += len(b.eth1DataVotes) * 72 - - // Field (11) 'validators' - size += len(b.validators) * 121 - - // Field (12) 'balances' - size += len(b.balances) * 8 - - // Field (15) 'previousEpochAttestations' - for ii := 0; ii < len(b.previousEpochAttestations); ii++ { - size += 4 - size += b.previousEpochAttestations[ii].SizeSSZ() - } - - // Field (16) 'currentEpochAttestations' - for ii := 0; ii < len(b.currentEpochAttestations); ii++ { - size += 4 - size += b.currentEpochAttestations[ii].SizeSSZ() - } - - return -} diff --git a/beacon-chain/state/state-native/v1/getters_block_test.go b/beacon-chain/state/state-native/v1/getters_block_test.go deleted file mode 100644 index 3cfae210b8..0000000000 --- a/beacon-chain/state/state-native/v1/getters_block_test.go +++ /dev/null @@ -1,45 +0,0 @@ -package v1 - -import ( - "testing" - - "github.com/prysmaticlabs/prysm/beacon-chain/state" - testtmpl "github.com/prysmaticlabs/prysm/beacon-chain/state/testing" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -func TestBeaconState_LatestBlockHeader(t *testing.T) { - testtmpl.VerifyBeaconStateLatestBlockHeader( - t, - func() (state.BeaconState, error) { - return InitializeFromProto(ðpb.BeaconState{}) - }, - func(BH *ethpb.BeaconBlockHeader) (state.BeaconState, error) { - return InitializeFromProto(ðpb.BeaconState{LatestBlockHeader: BH}) - }, - ) -} - -func TestBeaconState_BlockRoots(t *testing.T) { - testtmpl.VerifyBeaconStateBlockRootsNative( - t, - func() (state.BeaconState, error) { - return InitializeFromProto(ðpb.BeaconState{}) - }, - func(BR [][]byte) (state.BeaconState, error) { - return InitializeFromProto(ðpb.BeaconState{BlockRoots: BR}) - }, - ) -} - -func TestBeaconState_BlockRootAtIndex(t *testing.T) { - testtmpl.VerifyBeaconStateBlockRootAtIndexNative( - t, - func() (state.BeaconState, error) { - return InitializeFromProto(ðpb.BeaconState{}) - }, - func(BR [][]byte) (state.BeaconState, error) { - return InitializeFromProto(ðpb.BeaconState{BlockRoots: BR}) - }, - ) -} diff --git a/beacon-chain/state/state-native/v1/getters_checkpoint.go b/beacon-chain/state/state-native/v1/getters_checkpoint.go deleted file mode 100644 index 792948a643..0000000000 --- a/beacon-chain/state/state-native/v1/getters_checkpoint.go +++ /dev/null @@ -1,124 +0,0 @@ -package v1 - -import ( - "bytes" - - "github.com/prysmaticlabs/go-bitfield" - types "github.com/prysmaticlabs/prysm/consensus-types/primitives" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -// JustificationBits marking which epochs have been justified in the beacon chain. -func (b *BeaconState) JustificationBits() bitfield.Bitvector4 { - if b.justificationBits == nil { - return nil - } - - b.lock.RLock() - defer b.lock.RUnlock() - - return b.justificationBitsVal() -} - -// justificationBitsVal marking which epochs have been justified in the beacon chain. -// This assumes that a lock is already held on BeaconState. -func (b *BeaconState) justificationBitsVal() bitfield.Bitvector4 { - if b.justificationBits == nil { - return nil - } - - res := make([]byte, len(b.justificationBits.Bytes())) - copy(res, b.justificationBits.Bytes()) - return res -} - -// PreviousJustifiedCheckpoint denoting an epoch and block root. -func (b *BeaconState) PreviousJustifiedCheckpoint() *ethpb.Checkpoint { - if b.previousJustifiedCheckpoint == nil { - return nil - } - - b.lock.RLock() - defer b.lock.RUnlock() - - return b.previousJustifiedCheckpointVal() -} - -// previousJustifiedCheckpointVal denoting an epoch and block root. -// This assumes that a lock is already held on BeaconState. -func (b *BeaconState) previousJustifiedCheckpointVal() *ethpb.Checkpoint { - return ethpb.CopyCheckpoint(b.previousJustifiedCheckpoint) -} - -// CurrentJustifiedCheckpoint denoting an epoch and block root. -func (b *BeaconState) CurrentJustifiedCheckpoint() *ethpb.Checkpoint { - if b.currentJustifiedCheckpoint == nil { - return nil - } - - b.lock.RLock() - defer b.lock.RUnlock() - - return b.currentJustifiedCheckpointVal() -} - -// currentJustifiedCheckpointVal denoting an epoch and block root. -// This assumes that a lock is already held on BeaconState. -func (b *BeaconState) currentJustifiedCheckpointVal() *ethpb.Checkpoint { - return ethpb.CopyCheckpoint(b.currentJustifiedCheckpoint) -} - -// MatchCurrentJustifiedCheckpoint returns true if input justified checkpoint matches -// the current justified checkpoint in state. -func (b *BeaconState) MatchCurrentJustifiedCheckpoint(c *ethpb.Checkpoint) bool { - if b.currentJustifiedCheckpoint == nil { - return false - } - - if c.Epoch != b.currentJustifiedCheckpoint.Epoch { - return false - } - return bytes.Equal(c.Root, b.currentJustifiedCheckpoint.Root) -} - -// MatchPreviousJustifiedCheckpoint returns true if the input justified checkpoint matches -// the previous justified checkpoint in state. -func (b *BeaconState) MatchPreviousJustifiedCheckpoint(c *ethpb.Checkpoint) bool { - if b.previousJustifiedCheckpoint == nil { - return false - } - - if c.Epoch != b.previousJustifiedCheckpoint.Epoch { - return false - } - return bytes.Equal(c.Root, b.previousJustifiedCheckpoint.Root) -} - -// FinalizedCheckpoint denoting an epoch and block root. -func (b *BeaconState) FinalizedCheckpoint() *ethpb.Checkpoint { - if b.finalizedCheckpoint == nil { - return nil - } - - b.lock.RLock() - defer b.lock.RUnlock() - - return b.finalizedCheckpointVal() -} - -// finalizedCheckpointVal denoting an epoch and block root. -// This assumes that a lock is already held on BeaconState. -func (b *BeaconState) finalizedCheckpointVal() *ethpb.Checkpoint { - return ethpb.CopyCheckpoint(b.finalizedCheckpoint) -} - -// FinalizedCheckpointEpoch returns the epoch value of the finalized checkpoint. -func (b *BeaconState) FinalizedCheckpointEpoch() types.Epoch { - if b.finalizedCheckpoint == nil { - return 0 - } - b.lock.RLock() - defer b.lock.RUnlock() - - return b.finalizedCheckpoint.Epoch -} diff --git a/beacon-chain/state/state-native/v1/getters_checkpoint_test.go b/beacon-chain/state/state-native/v1/getters_checkpoint_test.go deleted file mode 100644 index dbe590a56f..0000000000 --- a/beacon-chain/state/state-native/v1/getters_checkpoint_test.go +++ /dev/null @@ -1,74 +0,0 @@ -package v1 - -import ( - "testing" - - "github.com/prysmaticlabs/go-bitfield" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - testtmpl "github.com/prysmaticlabs/prysm/beacon-chain/state/testing" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -func TestBeaconState_JustificationBitsNil(t *testing.T) { - testtmpl.VerifyBeaconStateJustificationBitsNil( - t, - func() (state.BeaconState, error) { - return InitializeFromProtoUnsafe(ðpb.BeaconState{}) - }) -} - -func TestBeaconState_JustificationBits(t *testing.T) { - testtmpl.VerifyBeaconStateJustificationBits( - t, - func(bits bitfield.Bitvector4) (state.BeaconState, error) { - return InitializeFromProtoUnsafe(ðpb.BeaconState{JustificationBits: bits}) - }) -} - -func TestBeaconState_PreviousJustifiedCheckpointNil(t *testing.T) { - testtmpl.VerifyBeaconStatePreviousJustifiedCheckpointNil( - t, - func() (state.BeaconState, error) { - return InitializeFromProtoUnsafe(ðpb.BeaconState{}) - }) -} - -func TestBeaconState_PreviousJustifiedCheckpoint(t *testing.T) { - testtmpl.VerifyBeaconStatePreviousJustifiedCheckpoint( - t, - func(cp *ethpb.Checkpoint) (state.BeaconState, error) { - return InitializeFromProtoUnsafe(ðpb.BeaconState{PreviousJustifiedCheckpoint: cp}) - }) -} - -func TestBeaconState_CurrentJustifiedCheckpointNil(t *testing.T) { - testtmpl.VerifyBeaconStateCurrentJustifiedCheckpointNil( - t, - func() (state.BeaconState, error) { - return InitializeFromProtoUnsafe(ðpb.BeaconState{}) - }) -} - -func TestBeaconState_CurrentJustifiedCheckpoint(t *testing.T) { - testtmpl.VerifyBeaconStateCurrentJustifiedCheckpoint( - t, - func(cp *ethpb.Checkpoint) (state.BeaconState, error) { - return InitializeFromProtoUnsafe(ðpb.BeaconState{CurrentJustifiedCheckpoint: cp}) - }) -} - -func TestBeaconState_FinalizedCheckpointNil(t *testing.T) { - testtmpl.VerifyBeaconStateFinalizedCheckpointNil( - t, - func() (state.BeaconState, error) { - return InitializeFromProtoUnsafe(ðpb.BeaconState{}) - }) -} - -func TestBeaconState_FinalizedCheckpoint(t *testing.T) { - testtmpl.VerifyBeaconStateFinalizedCheckpoint( - t, - func(cp *ethpb.Checkpoint) (state.BeaconState, error) { - return InitializeFromProtoUnsafe(ðpb.BeaconState{FinalizedCheckpoint: cp}) - }) -} diff --git a/beacon-chain/state/state-native/v1/getters_eth1.go b/beacon-chain/state/state-native/v1/getters_eth1.go deleted file mode 100644 index 35c0dea3ef..0000000000 --- a/beacon-chain/state/state-native/v1/getters_eth1.go +++ /dev/null @@ -1,64 +0,0 @@ -package v1 - -import ( - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -// Eth1Data corresponding to the proof-of-work chain information stored in the beacon state. -func (b *BeaconState) Eth1Data() *ethpb.Eth1Data { - if b.eth1Data == nil { - return nil - } - - b.lock.RLock() - defer b.lock.RUnlock() - - return b.eth1DataVal() -} - -// eth1DataVal corresponding to the proof-of-work chain information stored in the beacon state. -// This assumes that a lock is already held on BeaconState. -func (b *BeaconState) eth1DataVal() *ethpb.Eth1Data { - if b.eth1Data == nil { - return nil - } - - return ethpb.CopyETH1Data(b.eth1Data) -} - -// Eth1DataVotes corresponds to votes from Ethereum on the canonical proof-of-work chain -// data retrieved from eth1. -func (b *BeaconState) Eth1DataVotes() []*ethpb.Eth1Data { - if b.eth1DataVotes == nil { - return nil - } - - b.lock.RLock() - defer b.lock.RUnlock() - - return b.eth1DataVotesVal() -} - -// eth1DataVotesVal corresponds to votes from Ethereum on the canonical proof-of-work chain -// data retrieved from eth1. -// This assumes that a lock is already held on BeaconState. -func (b *BeaconState) eth1DataVotesVal() []*ethpb.Eth1Data { - if b.eth1DataVotes == nil { - return nil - } - - res := make([]*ethpb.Eth1Data, len(b.eth1DataVotes)) - for i := 0; i < len(res); i++ { - res[i] = ethpb.CopyETH1Data(b.eth1DataVotes[i]) - } - return res -} - -// Eth1DepositIndex corresponds to the index of the deposit made to the -// validator deposit contract at the time of this state's eth1 data. -func (b *BeaconState) Eth1DepositIndex() uint64 { - b.lock.RLock() - defer b.lock.RUnlock() - - return b.eth1DepositIndex -} diff --git a/beacon-chain/state/state-native/v1/getters_misc.go b/beacon-chain/state/state-native/v1/getters_misc.go deleted file mode 100644 index f0b132e52f..0000000000 --- a/beacon-chain/state/state-native/v1/getters_misc.go +++ /dev/null @@ -1,90 +0,0 @@ -package v1 - -import ( - types "github.com/prysmaticlabs/prysm/consensus-types/primitives" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/runtime/version" -) - -// GenesisTime of the beacon state as a uint64. -func (b *BeaconState) GenesisTime() uint64 { - b.lock.RLock() - defer b.lock.RUnlock() - - return b.genesisTime -} - -// GenesisValidatorsRoot of the beacon state. -func (b *BeaconState) GenesisValidatorsRoot() []byte { - b.lock.RLock() - defer b.lock.RUnlock() - - return b.genesisValidatorsRoot[:] -} - -// Version of the beacon state. This method -// is strictly meant to be used without a lock -// internally. -func (_ *BeaconState) Version() int { - return version.Phase0 -} - -// Slot of the current beacon chain state. -func (b *BeaconState) Slot() types.Slot { - b.lock.RLock() - defer b.lock.RUnlock() - - return b.slot -} - -// Fork version of the beacon chain. -func (b *BeaconState) Fork() *ethpb.Fork { - if b.fork == nil { - return nil - } - - b.lock.RLock() - defer b.lock.RUnlock() - - return b.forkVal() -} - -// forkVal version of the beacon chain. -// This assumes that a lock is already held on BeaconState. -func (b *BeaconState) forkVal() *ethpb.Fork { - if b.fork == nil { - return nil - } - - prevVersion := make([]byte, len(b.fork.PreviousVersion)) - copy(prevVersion, b.fork.PreviousVersion) - currVersion := make([]byte, len(b.fork.CurrentVersion)) - copy(currVersion, b.fork.CurrentVersion) - return ðpb.Fork{ - PreviousVersion: prevVersion, - CurrentVersion: currVersion, - Epoch: b.fork.Epoch, - } -} - -// HistoricalRoots based on epochs stored in the beacon state. -func (b *BeaconState) HistoricalRoots() [][]byte { - if b.historicalRoots == nil { - return nil - } - - b.lock.RLock() - defer b.lock.RUnlock() - - return b.historicalRoots.Slice() -} - -// balancesLength returns the length of the balances slice. -// This assumes that a lock is already held on BeaconState. -func (b *BeaconState) balancesLength() int { - if b.balances == nil { - return 0 - } - - return len(b.balances) -} diff --git a/beacon-chain/state/state-native/v1/getters_randao.go b/beacon-chain/state/state-native/v1/getters_randao.go deleted file mode 100644 index c22abceb08..0000000000 --- a/beacon-chain/state/state-native/v1/getters_randao.go +++ /dev/null @@ -1,66 +0,0 @@ -package v1 - -import ( - "fmt" -) - -// RandaoMixes of block proposers on the beacon chain. -func (b *BeaconState) RandaoMixes() [][]byte { - if b.randaoMixes == nil { - return nil - } - - b.lock.RLock() - defer b.lock.RUnlock() - - return b.randaoMixes.Slice() -} - -// RandaoMixAtIndex retrieves a specific block root based on an -// input index value. -func (b *BeaconState) RandaoMixAtIndex(idx uint64) ([]byte, error) { - if b.randaoMixes == nil { - return nil, nil - } - - b.lock.RLock() - defer b.lock.RUnlock() - - m, err := b.randaoMixAtIndex(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{}, fmt.Errorf("index %d out of range", idx) - } - return b.randaoMixes[idx], nil -} - -// RandaoMixesLength returns the length of the randao mixes slice. -func (b *BeaconState) RandaoMixesLength() int { - if b.randaoMixes == nil { - return 0 - } - - b.lock.RLock() - defer b.lock.RUnlock() - - return b.randaoMixesLength() -} - -// randaoMixesLength returns the length of the randao mixes slice. -// This assumes that a lock is already held on BeaconState. -func (b *BeaconState) randaoMixesLength() int { - if b.randaoMixes == nil { - return 0 - } - - return len(b.randaoMixes) -} diff --git a/beacon-chain/state/state-native/v1/getters_state.go b/beacon-chain/state/state-native/v1/getters_state.go deleted file mode 100644 index 4ce4e11fe1..0000000000 --- a/beacon-chain/state/state-native/v1/getters_state.go +++ /dev/null @@ -1,138 +0,0 @@ -package v1 - -import ( - "fmt" - - "github.com/pkg/errors" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -// ToProtoUnsafe returns the pointer value of the underlying -// beacon state proto object, bypassing immutability. Use with care. -func (b *BeaconState) ToProtoUnsafe() interface{} { - if b == nil { - return nil - } - - gvrCopy := b.genesisValidatorsRoot - - return ðpb.BeaconState{ - GenesisTime: b.genesisTime, - GenesisValidatorsRoot: gvrCopy[:], - Slot: b.slot, - Fork: b.fork, - LatestBlockHeader: b.latestBlockHeader, - BlockRoots: b.blockRoots.Slice(), - StateRoots: b.stateRoots.Slice(), - HistoricalRoots: b.historicalRoots.Slice(), - Eth1Data: b.eth1Data, - Eth1DataVotes: b.eth1DataVotes, - Eth1DepositIndex: b.eth1DepositIndex, - Validators: b.validators, - Balances: b.balances, - RandaoMixes: b.randaoMixes.Slice(), - Slashings: b.slashings, - PreviousEpochAttestations: b.previousEpochAttestations, - CurrentEpochAttestations: b.currentEpochAttestations, - JustificationBits: b.justificationBits, - PreviousJustifiedCheckpoint: b.previousJustifiedCheckpoint, - CurrentJustifiedCheckpoint: b.currentJustifiedCheckpoint, - FinalizedCheckpoint: b.finalizedCheckpoint, - } -} - -// ToProto the beacon state into a protobuf for usage. -func (b *BeaconState) ToProto() interface{} { - if b == nil { - return nil - } - - b.lock.RLock() - defer b.lock.RUnlock() - - gvrCopy := b.genesisValidatorsRoot - - return ðpb.BeaconState{ - GenesisTime: b.genesisTime, - GenesisValidatorsRoot: gvrCopy[:], - Slot: b.slot, - Fork: b.forkVal(), - LatestBlockHeader: b.latestBlockHeaderVal(), - BlockRoots: b.blockRoots.Slice(), - StateRoots: b.stateRoots.Slice(), - HistoricalRoots: b.historicalRoots.Slice(), - Eth1Data: b.eth1DataVal(), - Eth1DataVotes: b.eth1DataVotesVal(), - Eth1DepositIndex: b.eth1DepositIndex, - Validators: b.validatorsVal(), - Balances: b.balancesVal(), - RandaoMixes: b.randaoMixes.Slice(), - Slashings: b.slashingsVal(), - PreviousEpochAttestations: b.previousEpochAttestationsVal(), - CurrentEpochAttestations: b.currentEpochAttestationsVal(), - JustificationBits: b.justificationBitsVal(), - PreviousJustifiedCheckpoint: b.previousJustifiedCheckpointVal(), - CurrentJustifiedCheckpoint: b.currentJustifiedCheckpointVal(), - FinalizedCheckpoint: b.finalizedCheckpointVal(), - } -} - -// StateRoots kept track of in the beacon state. -func (b *BeaconState) StateRoots() [][]byte { - if b.stateRoots == nil { - return nil - } - - b.lock.RLock() - defer b.lock.RUnlock() - - return b.stateRoots.Slice() -} - -// StateRootAtIndex retrieves a specific state root based on an -// input index value. -func (b *BeaconState) StateRootAtIndex(idx uint64) ([]byte, error) { - if b.stateRoots == nil { - return nil, nil - } - - b.lock.RLock() - defer b.lock.RUnlock() - - r, err := b.stateRootAtIndex(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. -func (b *BeaconState) stateRootAtIndex(idx uint64) ([32]byte, error) { - if uint64(len(b.stateRoots)) <= idx { - return [32]byte{}, fmt.Errorf("index %d out of range", idx) - } - return b.stateRoots[idx], nil -} - -// ProtobufBeaconState transforms an input into beacon state in the form of protobuf. -// Error is returned if the input is not type protobuf beacon state. -func ProtobufBeaconState(s interface{}) (*ethpb.BeaconState, error) { - pbState, ok := s.(*ethpb.BeaconState) - if !ok { - return nil, errors.New("input is not type ethpb.BeaconState") - } - return pbState, nil -} - -// InnerStateUnsafe returns the pointer value of the underlying -// beacon state proto object, bypassing immutability. Use with care. -func (b *BeaconState) InnerStateUnsafe() interface{} { - return b.ToProtoUnsafe() -} - -// CloneInnerState the beacon state into a protobuf for usage. -func (b *BeaconState) CloneInnerState() interface{} { - return b.ToProto() -} diff --git a/beacon-chain/state/state-native/v1/getters_test.go b/beacon-chain/state/state-native/v1/getters_test.go deleted file mode 100644 index c748ebe601..0000000000 --- a/beacon-chain/state/state-native/v1/getters_test.go +++ /dev/null @@ -1,39 +0,0 @@ -package v1 - -import ( - "testing" - - "github.com/prysmaticlabs/prysm/beacon-chain/state" - testtmpl "github.com/prysmaticlabs/prysm/beacon-chain/state/testing" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -func TestBeaconState_SlotDataRace(t *testing.T) { - testtmpl.VerifyBeaconStateSlotDataRace(t, func() (state.BeaconState, error) { - return InitializeFromProto(ðpb.BeaconState{Slot: 1}) - }) -} - -func TestBeaconState_MatchCurrentJustifiedCheckpt(t *testing.T) { - testtmpl.VerifyBeaconStateMatchCurrentJustifiedCheckptNative( - t, - func(cp *ethpb.Checkpoint) (state.BeaconState, error) { - return InitializeFromProto(ðpb.BeaconState{CurrentJustifiedCheckpoint: cp}) - }, - ) -} - -func TestBeaconState_MatchPreviousJustifiedCheckpt(t *testing.T) { - testtmpl.VerifyBeaconStateMatchPreviousJustifiedCheckptNative( - t, - func(cp *ethpb.Checkpoint) (state.BeaconState, error) { - return InitializeFromProto(ðpb.BeaconState{PreviousJustifiedCheckpoint: cp}) - }, - ) -} - -func TestBeaconState_ValidatorByPubkey(t *testing.T) { - testtmpl.VerifyBeaconStateValidatorByPubkey(t, func() (state.BeaconState, error) { - return InitializeFromProto(ðpb.BeaconState{}) - }) -} diff --git a/beacon-chain/state/state-native/v1/getters_validator.go b/beacon-chain/state/state-native/v1/getters_validator.go deleted file mode 100644 index 29ce408b57..0000000000 --- a/beacon-chain/state/state-native/v1/getters_validator.go +++ /dev/null @@ -1,250 +0,0 @@ -package v1 - -import ( - "fmt" - - "github.com/pkg/errors" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" - types "github.com/prysmaticlabs/prysm/consensus-types/primitives" - "github.com/prysmaticlabs/prysm/encoding/bytesutil" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -// ValidatorIndexOutOfRangeError represents an error scenario where a validator does not exist -// at a given index in the validator's array. -type ValidatorIndexOutOfRangeError struct { - message string -} - -// NewValidatorIndexOutOfRangeError creates a new error instance. -func NewValidatorIndexOutOfRangeError(index types.ValidatorIndex) ValidatorIndexOutOfRangeError { - return ValidatorIndexOutOfRangeError{ - message: fmt.Sprintf("index %d out of range", index), - } -} - -// Error returns the underlying error message. -func (e *ValidatorIndexOutOfRangeError) Error() string { - return e.message -} - -// Validators participating in consensus on the beacon chain. -func (b *BeaconState) Validators() []*ethpb.Validator { - if b.validators == nil { - return nil - } - - b.lock.RLock() - defer b.lock.RUnlock() - - return b.validatorsVal() -} - -// validatorsVal participating in consensus on the beacon chain. -// This assumes that a lock is already held on BeaconState. -func (b *BeaconState) validatorsVal() []*ethpb.Validator { - if b.validators == nil { - return nil - } - - res := make([]*ethpb.Validator, len(b.validators)) - for i := 0; i < len(res); i++ { - val := b.validators[i] - if val == nil { - continue - } - res[i] = ethpb.CopyValidator(val) - } - 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)) - for i := 0; i < len(res); i++ { - validator := b.validators[i] - if validator == nil { - continue - } - // copy validator reference instead. - res[i] = validator - } - return res -} - -// ValidatorAtIndex is the validator at the provided index. -func (b *BeaconState) ValidatorAtIndex(idx types.ValidatorIndex) (*ethpb.Validator, error) { - if b.validators == nil { - return ðpb.Validator{}, nil - } - if uint64(len(b.validators)) <= uint64(idx) { - e := NewValidatorIndexOutOfRangeError(idx) - return nil, &e - } - - b.lock.RLock() - defer b.lock.RUnlock() - - val := b.validators[idx] - return ethpb.CopyValidator(val), nil -} - -// ValidatorAtIndexReadOnly is the validator at the provided index. This method -// doesn't clone the validator. -func (b *BeaconState) ValidatorAtIndexReadOnly(idx types.ValidatorIndex) (state.ReadOnlyValidator, error) { - if b.validators == nil { - return nil, state.ErrNilValidatorsInState - } - if uint64(len(b.validators)) <= uint64(idx) { - e := NewValidatorIndexOutOfRangeError(idx) - return nil, &e - } - - b.lock.RLock() - defer b.lock.RUnlock() - - return NewValidator(b.validators[idx]) -} - -// ValidatorIndexByPubkey returns a given validator by its 48-byte public key. -func (b *BeaconState) ValidatorIndexByPubkey(key [fieldparams.BLSPubkeyLength]byte) (types.ValidatorIndex, bool) { - if b == nil || b.valMapHandler == nil || b.valMapHandler.IsNil() { - return 0, false - } - b.lock.RLock() - defer b.lock.RUnlock() - numOfVals := len(b.validators) - - idx, ok := b.valMapHandler.Get(key) - if ok && types.ValidatorIndex(numOfVals) <= idx { - return types.ValidatorIndex(0), false - } - return idx, ok -} - -// PubkeyAtIndex returns the pubkey at the given -// validator index. -func (b *BeaconState) PubkeyAtIndex(idx types.ValidatorIndex) [fieldparams.BLSPubkeyLength]byte { - if uint64(idx) >= uint64(len(b.validators)) { - return [fieldparams.BLSPubkeyLength]byte{} - } - b.lock.RLock() - defer b.lock.RUnlock() - - if b.validators[idx] == nil { - return [fieldparams.BLSPubkeyLength]byte{} - } - return bytesutil.ToBytes48(b.validators[idx].PublicKey) -} - -// NumValidators returns the size of the validator registry. -func (b *BeaconState) NumValidators() int { - b.lock.RLock() - defer b.lock.RUnlock() - - return len(b.validators) -} - -// ReadFromEveryValidator reads values from every validator and applies it to the provided function. -// Warning: This method is potentially unsafe, as it exposes the actual validator registry. -func (b *BeaconState) ReadFromEveryValidator(f func(idx int, val state.ReadOnlyValidator) error) error { - if b.validators == nil { - return errors.New("nil validators in state") - } - b.lock.RLock() - validators := b.validators - b.lock.RUnlock() - - 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 -} - -// Balances of validators participating in consensus on the beacon chain. -func (b *BeaconState) Balances() []uint64 { - if b.balances == nil { - return nil - } - - b.lock.RLock() - defer b.lock.RUnlock() - - return b.balancesVal() -} - -// balances of validators participating in consensus on the beacon chain. -// This assumes that a lock is already held on BeaconState. -func (b *BeaconState) balancesVal() []uint64 { - if b.balances == nil { - return nil - } - - res := make([]uint64, len(b.balances)) - copy(res, b.balances) - return res -} - -// BalanceAtIndex of validator with the provided index. -func (b *BeaconState) BalanceAtIndex(idx types.ValidatorIndex) (uint64, error) { - if b.balances == nil { - return 0, nil - } - - b.lock.RLock() - defer b.lock.RUnlock() - - if uint64(len(b.balances)) <= uint64(idx) { - return 0, fmt.Errorf("index of %d does not exist", idx) - } - return b.balances[idx], nil -} - -// BalancesLength returns the length of the balances slice. -func (b *BeaconState) BalancesLength() int { - if b.balances == nil { - return 0 - } - - b.lock.RLock() - defer b.lock.RUnlock() - - return b.balancesLength() -} - -// Slashings of validators on the beacon chain. -func (b *BeaconState) Slashings() []uint64 { - if b.slashings == nil { - return nil - } - - b.lock.RLock() - defer b.lock.RUnlock() - - return b.slashingsVal() -} - -// slashings of validators on the beacon chain. -// This assumes that a lock is already held on BeaconState. -func (b *BeaconState) slashingsVal() []uint64 { - if b.slashings == nil { - return nil - } - - res := make([]uint64, len(b.slashings)) - copy(res, b.slashings) - return res -} diff --git a/beacon-chain/state/state-native/v1/getters_validator_test.go b/beacon-chain/state/state-native/v1/getters_validator_test.go deleted file mode 100644 index 7f35ad0bfd..0000000000 --- a/beacon-chain/state/state-native/v1/getters_validator_test.go +++ /dev/null @@ -1,18 +0,0 @@ -package v1_test - -import ( - "testing" - - "github.com/prysmaticlabs/prysm/beacon-chain/state" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/v1" - testtmpl "github.com/prysmaticlabs/prysm/beacon-chain/state/testing" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -func TestBeaconState_ValidatorAtIndexReadOnly_HandlesNilSlice(t *testing.T) { - testtmpl.VerifyBeaconStateValidatorAtIndexReadOnlyHandlesNilSlice(t, func() (state.BeaconState, error) { - return v1.InitializeFromProtoUnsafe(ðpb.BeaconState{ - Validators: nil, - }) - }) -} diff --git a/beacon-chain/state/state-native/v1/proofs.go b/beacon-chain/state/state-native/v1/proofs.go deleted file mode 100644 index 979ae04207..0000000000 --- a/beacon-chain/state/state-native/v1/proofs.go +++ /dev/null @@ -1,54 +0,0 @@ -package v1 - -import ( - "context" - "encoding/binary" - - "github.com/pkg/errors" - "github.com/prysmaticlabs/prysm/beacon-chain/state/fieldtrie" - "github.com/prysmaticlabs/prysm/encoding/bytesutil" -) - -const ( - finalizedRootIndex = uint64(105) // Precomputed value. -) - -// FinalizedRootGeneralizedIndex for the beacon state. -func FinalizedRootGeneralizedIndex() uint64 { - return finalizedRootIndex -} - -// CurrentSyncCommitteeProof from the state's Merkle trie representation. -func (*BeaconState) CurrentSyncCommitteeProof(_ context.Context) ([][]byte, error) { - return nil, errors.New("CurrentSyncCommitteeProof() unsupported for v1 beacon state") -} - -// NextSyncCommitteeProof from the state's Merkle trie representation. -func (*BeaconState) NextSyncCommitteeProof(_ context.Context) ([][]byte, error) { - return nil, errors.New("NextSyncCommitteeProof() unsupported for v1 beacon state") -} - -// FinalizedRootProof crafts a Merkle proof for the finalized root -// contained within the finalized checkpoint of a beacon state. -func (b *BeaconState) FinalizedRootProof(ctx context.Context) ([][]byte, error) { - b.lock.Lock() - defer b.lock.Unlock() - if err := b.initializeMerkleLayers(ctx); err != nil { - return nil, err - } - if err := b.recomputeDirtyFields(ctx); err != nil { - return nil, err - } - cpt := b.finalizedCheckpoint - // The epoch field of a finalized checkpoint is the neighbor - // index of the finalized root field in its Merkle tree representation - // of the checkpoint. This neighbor is the first element added to the proof. - epochBuf := make([]byte, 8) - binary.LittleEndian.PutUint64(epochBuf, uint64(cpt.Epoch)) - epochRoot := bytesutil.ToBytes32(epochBuf) - proof := make([][]byte, 0) - proof = append(proof, epochRoot[:]) - branch := fieldtrie.ProofFromMerkleLayers(b.merkleLayers, finalizedCheckpoint) - proof = append(proof, branch...) - return proof, nil -} diff --git a/beacon-chain/state/state-native/v1/references_test.go b/beacon-chain/state/state-native/v1/references_test.go deleted file mode 100644 index a54aa5bb83..0000000000 --- a/beacon-chain/state/state-native/v1/references_test.go +++ /dev/null @@ -1,393 +0,0 @@ -package v1 - -import ( - "reflect" - "runtime" - "runtime/debug" - "testing" - - "github.com/prysmaticlabs/go-bitfield" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - "github.com/prysmaticlabs/prysm/beacon-chain/state/types" - "github.com/prysmaticlabs/prysm/encoding/bytesutil" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/testing/assert" - "github.com/prysmaticlabs/prysm/testing/require" -) - -func TestStateReferenceSharing_Finalizer(t *testing.T) { - // This test showcases the logic on a the RandaoMixes field with the GC finalizer. - - a, err := InitializeFromProtoUnsafe(ðpb.BeaconState{RandaoMixes: [][]byte{[]byte("foo")}}) - require.NoError(t, err) - s, ok := a.(*BeaconState) - require.Equal(t, true, ok) - assert.Equal(t, uint(1), s.sharedFieldReferences[randaoMixes].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), s.sharedFieldReferences[randaoMixes].Refs(), "Expected 2 references to RANDAO mixes") - _ = b - }() - - runtime.GC() // Should run finalizer on object b - assert.Equal(t, uint(1), s.sharedFieldReferences[randaoMixes].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[randaoMixes].Refs(), "Expected 2 shared references to RANDAO mixes") - require.NoError(t, b.UpdateRandaoMixesAtIndex(0, []byte("bar"))) - if b.sharedFieldReferences[randaoMixes].Refs() != 1 || s.sharedFieldReferences[randaoMixes].Refs() != 1 { - t.Error("Expected 1 shared reference to RANDAO mix for both a and b") - } -} - -func TestStateReferenceCopy_NoUnexpectedRootsMutation(t *testing.T) { - root1, root2 := bytesutil.ToBytes32([]byte("foo")), bytesutil.ToBytes32([]byte("bar")) - a, err := InitializeFromProtoUnsafe(ðpb.BeaconState{ - BlockRoots: [][]byte{ - root1[:], - }, - StateRoots: [][]byte{ - root1[:], - }, - }) - require.NoError(t, err) - s, ok := a.(*BeaconState) - require.Equal(t, true, ok) - assertRefCount(t, s, blockRoots, 1) - assertRefCount(t, s, stateRoots, 1) - - // Copy, increases reference count. - copied := a.Copy() - b, ok := copied.(*BeaconState) - require.Equal(t, true, ok) - assertRefCount(t, s, blockRoots, 2) - assertRefCount(t, s, stateRoots, 2) - assertRefCount(t, b, blockRoots, 2) - assertRefCount(t, b, stateRoots, 2) - assert.Equal(t, 8192, len(b.BlockRoots()), "Wrong number of block roots found") - assert.Equal(t, 8192, len(b.StateRoots()), "Wrong number of state roots found") - - // Assert shared state. - blockRootsA := a.BlockRoots() - stateRootsA := a.StateRoots() - blockRootsB := b.BlockRoots() - stateRootsB := b.StateRoots() - if len(blockRootsA) != len(blockRootsB) || len(blockRootsA) < 1 { - t.Errorf("Unexpected number of block roots, want: %v", 1) - } - if len(stateRootsA) != len(stateRootsB) || len(stateRootsA) < 1 { - t.Errorf("Unexpected number of state roots, want: %v", 1) - } - assertValFound(t, blockRootsA, root1[:]) - assertValFound(t, blockRootsB, root1[:]) - assertValFound(t, stateRootsA, root1[:]) - assertValFound(t, stateRootsB, root1[:]) - - // Mutator should only affect calling state: a. - require.NoError(t, a.UpdateBlockRootAtIndex(0, root2)) - require.NoError(t, a.UpdateStateRootAtIndex(0, root2)) - - // 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[:]) - if len(blockRootsA) != len(blockRootsB) || len(blockRootsA) < 1 { - t.Errorf("Unexpected number of block roots, want: %v", 1) - } - if len(stateRootsA) != len(stateRootsB) || len(stateRootsA) < 1 { - t.Errorf("Unexpected number of state roots, want: %v", 1) - } - 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") - - // Copy on write happened, reference counters are reset. - assertRefCount(t, s, blockRoots, 1) - assertRefCount(t, s, stateRoots, 1) - assertRefCount(t, b, blockRoots, 1) - assertRefCount(t, b, stateRoots, 1) -} - -func TestStateReferenceCopy_NoUnexpectedRandaoMutation(t *testing.T) { - - val1, val2 := bytesutil.PadTo([]byte("foo"), 32), bytesutil.PadTo([]byte("bar"), 32) - a, err := InitializeFromProtoUnsafe(ðpb.BeaconState{ - RandaoMixes: [][]byte{ - val1, - }, - }) - require.NoError(t, err) - s, ok := a.(*BeaconState) - require.Equal(t, true, ok) - assertRefCount(t, s, randaoMixes, 1) - - // Copy, increases reference count. - copied := a.Copy() - b, ok := copied.(*BeaconState) - require.Equal(t, true, ok) - assertRefCount(t, s, randaoMixes, 2) - assertRefCount(t, b, randaoMixes, 2) - - // Assert shared state. - mixesA := a.RandaoMixes() - mixesB := b.RandaoMixes() - if len(mixesA) != len(mixesB) || len(mixesA) < 1 { - t.Errorf("Unexpected number of mix values, want: %v", 1) - } - 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). - if len(mixesA) != len(mixesB) || len(mixesA) < 1 { - t.Errorf("Unexpected number of mix values, want: %v", 1) - } - 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, s, randaoMixes, 1) - assertRefCount(t, b, randaoMixes, 1) -} - -func TestStateReferenceCopy_NoUnexpectedAttestationsMutation(t *testing.T) { - assertAttFound := func(vals []*ethpb.PendingAttestation, val uint64) { - for i := range vals { - if reflect.DeepEqual(vals[i].AggregationBits, bitfield.NewBitlist(val)) { - return - } - } - t.Log(string(debug.Stack())) - t.Fatalf("Expected attestation not found (%v), want: %v", vals, val) - } - assertAttNotFound := func(vals []*ethpb.PendingAttestation, val uint64) { - for i := range vals { - if reflect.DeepEqual(vals[i].AggregationBits, bitfield.NewBitlist(val)) { - t.Log(string(debug.Stack())) - t.Fatalf("Unexpected attestation found (%v): %v", vals, val) - return - } - } - } - - a, err := InitializeFromProtoUnsafe(ðpb.BeaconState{}) - require.NoError(t, err) - s, ok := a.(*BeaconState) - require.Equal(t, true, ok) - assertRefCount(t, s, previousEpochAttestations, 1) - assertRefCount(t, s, currentEpochAttestations, 1) - - // Update initial state. - atts := []*ethpb.PendingAttestation{ - {AggregationBits: bitfield.NewBitlist(1)}, - {AggregationBits: bitfield.NewBitlist(2)}, - } - s.setPreviousEpochAttestations(atts[:1]) - s.setCurrentEpochAttestations(atts[:1]) - curAtt, err := a.CurrentEpochAttestations() - require.NoError(t, err) - assert.Equal(t, 1, len(curAtt), "Unexpected number of attestations") - preAtt, err := a.PreviousEpochAttestations() - require.NoError(t, err) - assert.Equal(t, 1, len(preAtt), "Unexpected number of attestations") - - // Copy, increases reference count. - copied := a.Copy() - b, ok := copied.(*BeaconState) - require.Equal(t, true, ok) - assertRefCount(t, s, previousEpochAttestations, 2) - assertRefCount(t, s, currentEpochAttestations, 2) - assertRefCount(t, b, previousEpochAttestations, 2) - assertRefCount(t, b, currentEpochAttestations, 2) - bPrevEpochAtts, err := b.PreviousEpochAttestations() - require.NoError(t, err) - bCurrEpochAtts, err := b.CurrentEpochAttestations() - require.NoError(t, err) - assert.Equal(t, 1, len(bPrevEpochAtts), "Unexpected number of attestations") - assert.Equal(t, 1, len(bCurrEpochAtts), "Unexpected number of attestations") - - // Assert shared state. - aCurrEpochAtts, err := a.CurrentEpochAttestations() - require.NoError(t, err) - curAttsA := aCurrEpochAtts - aPrevEpochAtts, err := a.PreviousEpochAttestations() - require.NoError(t, err) - prevAttsA := aPrevEpochAtts - bCurrEpochAtts, err = b.CurrentEpochAttestations() - require.NoError(t, err) - curAttsB := bCurrEpochAtts - bPrevEpochAtts, err = b.PreviousEpochAttestations() - require.NoError(t, err) - prevAttsB := bPrevEpochAtts - if len(curAttsA) != len(curAttsB) || len(curAttsA) < 1 { - t.Errorf("Unexpected number of attestations, want: %v", 1) - } - if len(prevAttsA) != len(prevAttsB) || len(prevAttsA) < 1 { - t.Errorf("Unexpected number of attestations, want: %v", 1) - } - assertAttFound(curAttsA, 1) - assertAttFound(prevAttsA, 1) - assertAttFound(curAttsB, 1) - assertAttFound(prevAttsB, 1) - - // Extends state a attestations. - require.NoError(t, a.AppendCurrentEpochAttestations(atts[1])) - require.NoError(t, a.AppendPreviousEpochAttestations(atts[1])) - curAtt, err = a.CurrentEpochAttestations() - require.NoError(t, err) - assert.Equal(t, 2, len(curAtt), "Unexpected number of attestations") - preAtt, err = a.PreviousEpochAttestations() - require.NoError(t, err) - assert.Equal(t, 2, len(preAtt), "Unexpected number of attestations") - aCurrEpochAtts, err = a.CurrentEpochAttestations() - require.NoError(t, err) - aPrevEpochAtts, err = a.PreviousEpochAttestations() - require.NoError(t, err) - bCurrEpochAtts, err = b.CurrentEpochAttestations() - require.NoError(t, err) - bPrevEpochAtts, err = b.PreviousEpochAttestations() - require.NoError(t, err) - assertAttFound(aCurrEpochAtts, 1) - assertAttFound(aPrevEpochAtts, 1) - assertAttFound(aCurrEpochAtts, 2) - assertAttFound(aPrevEpochAtts, 2) - assertAttFound(bCurrEpochAtts, 1) - assertAttFound(bPrevEpochAtts, 1) - assertAttNotFound(bCurrEpochAtts, 2) - assertAttNotFound(bPrevEpochAtts, 2) - - // Mutator should only affect calling state: a. - applyToEveryAttestation := func(state *BeaconState) { - // One MUST copy on write. - atts = make([]*ethpb.PendingAttestation, len(state.currentEpochAttestations)) - copy(atts, state.currentEpochAttestations) - state.currentEpochAttestations = atts - currEpochAtts, err := state.CurrentEpochAttestations() - require.NoError(t, err) - for i := range currEpochAtts { - att := ethpb.CopyPendingAttestation(state.currentEpochAttestations[i]) - att.AggregationBits = bitfield.NewBitlist(3) - state.currentEpochAttestations[i] = att - } - - atts = make([]*ethpb.PendingAttestation, len(state.previousEpochAttestations)) - copy(atts, state.previousEpochAttestations) - state.previousEpochAttestations = atts - prevEpochAtts, err := state.PreviousEpochAttestations() - require.NoError(t, err) - for i := range prevEpochAtts { - att := ethpb.CopyPendingAttestation(state.previousEpochAttestations[i]) - att.AggregationBits = bitfield.NewBitlist(3) - state.previousEpochAttestations[i] = att - } - } - applyToEveryAttestation(s) - - aCurrEpochAtts, err = a.CurrentEpochAttestations() - require.NoError(t, err) - aPrevEpochAtts, err = a.PreviousEpochAttestations() - require.NoError(t, err) - bCurrEpochAtts, err = b.CurrentEpochAttestations() - require.NoError(t, err) - bPrevEpochAtts, err = b.PreviousEpochAttestations() - require.NoError(t, err) - // Assert no shared state mutation occurred only on state a (copy on write). - assertAttFound(aCurrEpochAtts, 3) - assertAttFound(aPrevEpochAtts, 3) - assertAttNotFound(aCurrEpochAtts, 1) - assertAttNotFound(aPrevEpochAtts, 1) - assertAttNotFound(aCurrEpochAtts, 2) - assertAttNotFound(aPrevEpochAtts, 2) - // State b must be unaffected. - assertAttNotFound(bCurrEpochAtts, 3) - assertAttNotFound(bPrevEpochAtts, 3) - assertAttFound(bCurrEpochAtts, 1) - assertAttFound(bPrevEpochAtts, 1) - assertAttNotFound(bCurrEpochAtts, 2) - assertAttNotFound(bPrevEpochAtts, 2) - - // Copy on write happened, reference counters are reset. - assertRefCount(t, s, currentEpochAttestations, 1) - assertRefCount(t, b, currentEpochAttestations, 1) - assertRefCount(t, s, previousEpochAttestations, 1) - assertRefCount(t, b, previousEpochAttestations, 1) -} - -func TestValidatorReferences_RemainsConsistent(t *testing.T) { - a, err := InitializeFromProtoUnsafe(ðpb.BeaconState{ - Validators: []*ethpb.Validator{ - {PublicKey: []byte{'A'}}, - {PublicKey: []byte{'B'}}, - {PublicKey: []byte{'C'}}, - {PublicKey: []byte{'D'}}, - {PublicKey: []byte{'E'}}, - }, - }) - require.NoError(t, err) - - // Create a second state. - copied := a.Copy() - b, ok := copied.(*BeaconState) - require.Equal(t, true, ok) - - // Update First Validator. - assert.NoError(t, a.UpdateValidatorAtIndex(0, ðpb.Validator{PublicKey: []byte{'Z'}})) - - assert.DeepNotEqual(t, a.Validators()[0], b.Validators()[0], "validators are equal when they are supposed to be different") - // Modify all validators from copied state. - assert.NoError(t, b.ApplyToEveryValidator(func(idx int, val *ethpb.Validator) (bool, *ethpb.Validator, error) { - return true, ðpb.Validator{PublicKey: []byte{'V'}}, nil - })) - - // Ensure reference is properly accounted for. - assert.NoError(t, a.ReadFromEveryValidator(func(idx int, val state.ReadOnlyValidator) error { - assert.NotEqual(t, bytesutil.ToBytes48([]byte{'V'}), val.PublicKey()) - return nil - })) -} - -// assertRefCount checks whether reference count for a given state -// at a given index is equal to expected amount. -func assertRefCount(t *testing.T, b *BeaconState, idx types.FieldIndex, want uint) { - if cnt := b.sharedFieldReferences[idx].Refs(); cnt != want { - t.Errorf("Unexpected count of references for index %d, want: %v, got: %v", idx, want, cnt) - } -} - -// assertValFound checks whether item with a given value exists in list. -func assertValFound(t *testing.T, vals [][]byte, val []byte) { - for i := range vals { - if reflect.DeepEqual(vals[i], val) { - return - } - } - t.Log(string(debug.Stack())) - t.Fatalf("Expected value not found (%v), want: %v", vals, val) -} - -// assertValNotFound checks whether item with a given value doesn't exist in list. -func assertValNotFound(t *testing.T, vals [][]byte, val []byte) { - for i := range vals { - if reflect.DeepEqual(vals[i], val) { - t.Log(string(debug.Stack())) - t.Errorf("Unexpected value found (%v),: %v", vals, val) - return - } - } -} diff --git a/beacon-chain/state/state-native/v1/setters_checkpoint.go b/beacon-chain/state/state-native/v1/setters_checkpoint.go deleted file mode 100644 index 66730692eb..0000000000 --- a/beacon-chain/state/state-native/v1/setters_checkpoint.go +++ /dev/null @@ -1,46 +0,0 @@ -package v1 - -import ( - "github.com/prysmaticlabs/go-bitfield" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -// SetJustificationBits for the beacon state. -func (b *BeaconState) SetJustificationBits(val bitfield.Bitvector4) error { - b.lock.Lock() - defer b.lock.Unlock() - - b.justificationBits = val - b.markFieldAsDirty(justificationBits) - return nil -} - -// SetPreviousJustifiedCheckpoint for the beacon state. -func (b *BeaconState) SetPreviousJustifiedCheckpoint(val *ethpb.Checkpoint) error { - b.lock.Lock() - defer b.lock.Unlock() - - b.previousJustifiedCheckpoint = val - b.markFieldAsDirty(previousJustifiedCheckpoint) - return nil -} - -// SetCurrentJustifiedCheckpoint for the beacon state. -func (b *BeaconState) SetCurrentJustifiedCheckpoint(val *ethpb.Checkpoint) error { - b.lock.Lock() - defer b.lock.Unlock() - - b.currentJustifiedCheckpoint = val - b.markFieldAsDirty(currentJustifiedCheckpoint) - return nil -} - -// SetFinalizedCheckpoint for the beacon state. -func (b *BeaconState) SetFinalizedCheckpoint(val *ethpb.Checkpoint) error { - b.lock.Lock() - defer b.lock.Unlock() - - b.finalizedCheckpoint = val - b.markFieldAsDirty(finalizedCheckpoint) - return nil -} diff --git a/beacon-chain/state/state-native/v1/setters_eth1.go b/beacon-chain/state/state-native/v1/setters_eth1.go deleted file mode 100644 index ce3d6af567..0000000000 --- a/beacon-chain/state/state-native/v1/setters_eth1.go +++ /dev/null @@ -1,62 +0,0 @@ -package v1 - -import ( - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -// SetEth1Data for the beacon state. -func (b *BeaconState) SetEth1Data(val *ethpb.Eth1Data) error { - b.lock.Lock() - defer b.lock.Unlock() - - b.eth1Data = val - b.markFieldAsDirty(eth1Data) - return nil -} - -// SetEth1DataVotes for the beacon state. Updates the entire -// list to a new value by overwriting the previous one. -func (b *BeaconState) SetEth1DataVotes(val []*ethpb.Eth1Data) error { - b.lock.Lock() - defer b.lock.Unlock() - - b.sharedFieldReferences[eth1DataVotes].MinusRef() - b.sharedFieldReferences[eth1DataVotes] = stateutil.NewRef(1) - - b.eth1DataVotes = val - b.markFieldAsDirty(eth1DataVotes) - b.rebuildTrie[eth1DataVotes] = true - return nil -} - -// SetEth1DepositIndex for the beacon state. -func (b *BeaconState) SetEth1DepositIndex(val uint64) error { - b.lock.Lock() - defer b.lock.Unlock() - - b.eth1DepositIndex = val - b.markFieldAsDirty(eth1DepositIndex) - return nil -} - -// AppendEth1DataVotes for the beacon state. Appends the new value -// to the the end of list. -func (b *BeaconState) AppendEth1DataVotes(val *ethpb.Eth1Data) error { - b.lock.Lock() - defer b.lock.Unlock() - - votes := b.eth1DataVotes - if b.sharedFieldReferences[eth1DataVotes].Refs() > 1 { - // Copy elements in underlying array by reference. - votes = make([]*ethpb.Eth1Data, len(b.eth1DataVotes)) - copy(votes, b.eth1DataVotes) - b.sharedFieldReferences[eth1DataVotes].MinusRef() - b.sharedFieldReferences[eth1DataVotes] = stateutil.NewRef(1) - } - - b.eth1DataVotes = append(votes, val) - b.markFieldAsDirty(eth1DataVotes) - b.addDirtyIndices(eth1DataVotes, []uint64{uint64(len(b.eth1DataVotes) - 1)}) - return nil -} diff --git a/beacon-chain/state/state-native/v1/setters_validator.go b/beacon-chain/state/state-native/v1/setters_validator.go deleted file mode 100644 index b96ff73e83..0000000000 --- a/beacon-chain/state/state-native/v1/setters_validator.go +++ /dev/null @@ -1,201 +0,0 @@ -package v1 - -import ( - "github.com/pkg/errors" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - types "github.com/prysmaticlabs/prysm/consensus-types/primitives" - "github.com/prysmaticlabs/prysm/encoding/bytesutil" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -// SetValidators for the beacon state. Updates the entire -// to a new value by overwriting the previous one. -func (b *BeaconState) SetValidators(val []*ethpb.Validator) error { - b.lock.Lock() - defer b.lock.Unlock() - - b.validators = val - b.sharedFieldReferences[validators].MinusRef() - b.sharedFieldReferences[validators] = stateutil.NewRef(1) - b.markFieldAsDirty(validators) - b.rebuildTrie[validators] = true - b.valMapHandler = stateutil.NewValMapHandler(b.validators) - return nil -} - -// ApplyToEveryValidator applies the provided callback function to each validator in the -// validator registry. -func (b *BeaconState) ApplyToEveryValidator(f func(idx int, val *ethpb.Validator) (bool, *ethpb.Validator, error)) error { - b.lock.Lock() - v := b.validators - if ref := b.sharedFieldReferences[validators]; ref.Refs() > 1 { - v = b.validatorsReferences() - ref.MinusRef() - b.sharedFieldReferences[validators] = stateutil.NewRef(1) - } - b.lock.Unlock() - var changedVals []uint64 - for i, val := range v { - changed, newVal, err := f(i, val) - if err != nil { - return err - } - if changed { - changedVals = append(changedVals, uint64(i)) - v[i] = newVal - } - } - - b.lock.Lock() - defer b.lock.Unlock() - - b.validators = v - b.markFieldAsDirty(validators) - b.addDirtyIndices(validators, changedVals) - - return nil -} - -// UpdateValidatorAtIndex for the beacon state. Updates the validator -// at a specific index to a new value. -func (b *BeaconState) UpdateValidatorAtIndex(idx types.ValidatorIndex, val *ethpb.Validator) error { - if uint64(len(b.validators)) <= uint64(idx) { - return errors.Errorf("invalid index provided %d", idx) - } - b.lock.Lock() - defer b.lock.Unlock() - - v := b.validators - if ref := b.sharedFieldReferences[validators]; ref.Refs() > 1 { - v = b.validatorsReferences() - ref.MinusRef() - b.sharedFieldReferences[validators] = stateutil.NewRef(1) - } - - v[idx] = val - b.validators = v - b.markFieldAsDirty(validators) - b.addDirtyIndices(validators, []uint64{uint64(idx)}) - - return nil -} - -// SetBalances for the beacon state. Updates the entire -// list to a new value by overwriting the previous one. -func (b *BeaconState) SetBalances(val []uint64) error { - b.lock.Lock() - defer b.lock.Unlock() - - b.sharedFieldReferences[balances].MinusRef() - b.sharedFieldReferences[balances] = stateutil.NewRef(1) - - b.balances = val - b.markFieldAsDirty(balances) - b.rebuildTrie[balances] = true - return nil -} - -// UpdateBalancesAtIndex for the beacon state. This method updates the balance -// at a specific index to a new value. -func (b *BeaconState) UpdateBalancesAtIndex(idx types.ValidatorIndex, val uint64) error { - if uint64(len(b.balances)) <= uint64(idx) { - return errors.Errorf("invalid index provided %d", idx) - } - b.lock.Lock() - defer b.lock.Unlock() - - bals := b.balances - if b.sharedFieldReferences[balances].Refs() > 1 { - bals = b.balancesVal() - b.sharedFieldReferences[balances].MinusRef() - b.sharedFieldReferences[balances] = stateutil.NewRef(1) - } - - bals[idx] = val - b.balances = bals - b.markFieldAsDirty(balances) - b.addDirtyIndices(balances, []uint64{uint64(idx)}) - return nil -} - -// SetSlashings for the beacon state. Updates the entire -// list to a new value by overwriting the previous one. -func (b *BeaconState) SetSlashings(val []uint64) error { - b.lock.Lock() - defer b.lock.Unlock() - - b.sharedFieldReferences[slashings].MinusRef() - b.sharedFieldReferences[slashings] = stateutil.NewRef(1) - - b.slashings = val - b.markFieldAsDirty(slashings) - return nil -} - -// UpdateSlashingsAtIndex for the beacon state. Updates the slashings -// at a specific index to a new value. -func (b *BeaconState) UpdateSlashingsAtIndex(idx, val uint64) error { - if uint64(len(b.slashings)) <= idx { - return errors.Errorf("invalid index provided %d", idx) - } - b.lock.Lock() - defer b.lock.Unlock() - - s := b.slashings - if b.sharedFieldReferences[slashings].Refs() > 1 { - s = b.slashingsVal() - b.sharedFieldReferences[slashings].MinusRef() - b.sharedFieldReferences[slashings] = stateutil.NewRef(1) - } - - s[idx] = val - - b.slashings = s - - b.markFieldAsDirty(slashings) - return nil -} - -// AppendValidator for the beacon state. Appends the new value -// to the the end of list. -func (b *BeaconState) AppendValidator(val *ethpb.Validator) error { - b.lock.Lock() - defer b.lock.Unlock() - - vals := b.validators - if b.sharedFieldReferences[validators].Refs() > 1 { - vals = b.validatorsReferences() - b.sharedFieldReferences[validators].MinusRef() - b.sharedFieldReferences[validators] = stateutil.NewRef(1) - } - - // append validator to slice - b.validators = append(vals, val) - valIdx := types.ValidatorIndex(len(b.validators) - 1) - - b.valMapHandler.Set(bytesutil.ToBytes48(val.PublicKey), valIdx) - - b.markFieldAsDirty(validators) - b.addDirtyIndices(validators, []uint64{uint64(valIdx)}) - return nil -} - -// AppendBalance for the beacon state. Appends the new value -// to the the end of list. -func (b *BeaconState) AppendBalance(bal uint64) error { - b.lock.Lock() - defer b.lock.Unlock() - - bals := b.balances - if b.sharedFieldReferences[balances].Refs() > 1 { - bals = b.balancesVal() - b.sharedFieldReferences[balances].MinusRef() - b.sharedFieldReferences[balances] = stateutil.NewRef(1) - } - - b.balances = append(bals, bal) - balIdx := len(b.balances) - 1 - b.markFieldAsDirty(balances) - b.addDirtyIndices(balances, []uint64{uint64(balIdx)}) - return nil -} diff --git a/beacon-chain/state/state-native/v1/state_trie.go b/beacon-chain/state/state-native/v1/state_trie.go deleted file mode 100644 index f08446510c..0000000000 --- a/beacon-chain/state/state-native/v1/state_trie.go +++ /dev/null @@ -1,475 +0,0 @@ -package v1 - -import ( - "context" - "runtime" - "sort" - - "github.com/pkg/errors" - - "github.com/prysmaticlabs/prysm/beacon-chain/state" - "github.com/prysmaticlabs/prysm/beacon-chain/state/fieldtrie" - customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - "github.com/prysmaticlabs/prysm/beacon-chain/state/types" - fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" - "github.com/prysmaticlabs/prysm/config/params" - "github.com/prysmaticlabs/prysm/container/slice" - "github.com/prysmaticlabs/prysm/crypto/hash" - "github.com/prysmaticlabs/prysm/encoding/bytesutil" - "github.com/prysmaticlabs/prysm/encoding/ssz" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" - "go.opencensus.io/trace" - "google.golang.org/protobuf/proto" -) - -// InitializeFromProto the beacon state from a protobuf representation. -func InitializeFromProto(st *ethpb.BeaconState) (state.BeaconState, error) { - return InitializeFromProtoUnsafe(proto.Clone(st).(*ethpb.BeaconState)) -} - -// InitializeFromProtoUnsafe directly uses the beacon state protobuf fields -// and sets them as fields of the BeaconState type. -func InitializeFromProtoUnsafe(st *ethpb.BeaconState) (state.BeaconState, error) { - if st == nil { - return nil, errors.New("received nil state") - } - - var bRoots customtypes.BlockRoots - for i, r := range st.BlockRoots { - copy(bRoots[i][:], r) - } - var sRoots customtypes.StateRoots - for i, r := range st.StateRoots { - copy(sRoots[i][:], r) - } - hRoots := customtypes.HistoricalRoots(make([][32]byte, len(st.HistoricalRoots))) - for i, r := range st.HistoricalRoots { - copy(hRoots[i][:], r) - } - var mixes customtypes.RandaoMixes - for i, m := range st.RandaoMixes { - copy(mixes[i][:], m) - } - - fieldCount := params.BeaconConfig().BeaconStateFieldCount - b := &BeaconState{ - genesisTime: st.GenesisTime, - genesisValidatorsRoot: bytesutil.ToBytes32(st.GenesisValidatorsRoot), - slot: st.Slot, - fork: st.Fork, - latestBlockHeader: st.LatestBlockHeader, - blockRoots: &bRoots, - stateRoots: &sRoots, - historicalRoots: hRoots, - eth1Data: st.Eth1Data, - eth1DataVotes: st.Eth1DataVotes, - eth1DepositIndex: st.Eth1DepositIndex, - validators: st.Validators, - balances: st.Balances, - randaoMixes: &mixes, - slashings: st.Slashings, - previousEpochAttestations: st.PreviousEpochAttestations, - currentEpochAttestations: st.CurrentEpochAttestations, - justificationBits: st.JustificationBits, - previousJustifiedCheckpoint: st.PreviousJustifiedCheckpoint, - currentJustifiedCheckpoint: st.CurrentJustifiedCheckpoint, - finalizedCheckpoint: st.FinalizedCheckpoint, - - dirtyFields: make(map[types.FieldIndex]bool, fieldCount), - dirtyIndices: make(map[types.FieldIndex][]uint64, fieldCount), - stateFieldLeaves: make(map[types.FieldIndex]*fieldtrie.FieldTrie, fieldCount), - sharedFieldReferences: make(map[types.FieldIndex]*stateutil.Reference, 10), - rebuildTrie: make(map[types.FieldIndex]bool, fieldCount), - valMapHandler: stateutil.NewValMapHandler(st.Validators), - } - - var err error - for i := 0; i < fieldCount; i++ { - b.dirtyFields[types.FieldIndex(i)] = true - b.rebuildTrie[types.FieldIndex(i)] = true - b.dirtyIndices[types.FieldIndex(i)] = []uint64{} - b.stateFieldLeaves[types.FieldIndex(i)], err = fieldtrie.NewFieldTrie(types.FieldIndex(i), types.BasicArray, nil, 0) - if err != nil { - return nil, err - } - } - - // Initialize field reference tracking for shared data. - b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1) - b.sharedFieldReferences[stateRoots] = stateutil.NewRef(1) - b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1) - b.sharedFieldReferences[previousEpochAttestations] = stateutil.NewRef(1) - b.sharedFieldReferences[currentEpochAttestations] = stateutil.NewRef(1) - b.sharedFieldReferences[slashings] = stateutil.NewRef(1) - b.sharedFieldReferences[eth1DataVotes] = stateutil.NewRef(1) - b.sharedFieldReferences[validators] = stateutil.NewRef(1) - b.sharedFieldReferences[balances] = stateutil.NewRef(1) - b.sharedFieldReferences[historicalRoots] = stateutil.NewRef(1) - - state.StateCount.Inc() - return b, nil -} - -// Copy returns a deep copy of the beacon state. -func (b *BeaconState) Copy() state.BeaconState { - b.lock.RLock() - defer b.lock.RUnlock() - fieldCount := params.BeaconConfig().BeaconStateFieldCount - dst := &BeaconState{ - // Primitive types, safe to copy. - genesisTime: b.genesisTime, - slot: b.slot, - eth1DepositIndex: b.eth1DepositIndex, - - // Large arrays, infrequently changed, constant size. - slashings: b.slashings, - - // Large arrays, infrequently changed, constant size. - blockRoots: b.blockRoots, - stateRoots: b.stateRoots, - randaoMixes: b.randaoMixes, - previousEpochAttestations: b.previousEpochAttestations, - currentEpochAttestations: b.currentEpochAttestations, - eth1DataVotes: b.eth1DataVotes, - - // Large arrays, increases over time. - balances: b.balances, - historicalRoots: b.historicalRoots, - validators: b.validators, - - // Everything else, too small to be concerned about, constant size. - genesisValidatorsRoot: b.genesisValidatorsRoot, - justificationBits: b.justificationBitsVal(), - fork: b.forkVal(), - latestBlockHeader: b.latestBlockHeaderVal(), - eth1Data: b.eth1DataVal(), - previousJustifiedCheckpoint: b.previousJustifiedCheckpointVal(), - currentJustifiedCheckpoint: b.currentJustifiedCheckpointVal(), - finalizedCheckpoint: b.finalizedCheckpointVal(), - - dirtyFields: make(map[types.FieldIndex]bool, fieldCount), - dirtyIndices: make(map[types.FieldIndex][]uint64, fieldCount), - rebuildTrie: make(map[types.FieldIndex]bool, fieldCount), - sharedFieldReferences: make(map[types.FieldIndex]*stateutil.Reference, 10), - stateFieldLeaves: make(map[types.FieldIndex]*fieldtrie.FieldTrie, fieldCount), - - // Share the reference to validator index map. - valMapHandler: b.valMapHandler, - } - - for field, ref := range b.sharedFieldReferences { - ref.AddRef() - dst.sharedFieldReferences[field] = ref - } - - // Increment ref for validator map - b.valMapHandler.AddRef() - - for i := range b.dirtyFields { - dst.dirtyFields[i] = true - } - - for i := range b.dirtyIndices { - indices := make([]uint64, len(b.dirtyIndices[i])) - copy(indices, b.dirtyIndices[i]) - dst.dirtyIndices[i] = indices - } - - for i := range b.rebuildTrie { - dst.rebuildTrie[i] = true - } - - for fldIdx, fieldTrie := range b.stateFieldLeaves { - dst.stateFieldLeaves[fldIdx] = fieldTrie - if fieldTrie.FieldReference() != nil { - fieldTrie.Lock() - fieldTrie.FieldReference().AddRef() - fieldTrie.Unlock() - } - } - - if b.merkleLayers != nil { - dst.merkleLayers = make([][][]byte, len(b.merkleLayers)) - for i, layer := range b.merkleLayers { - dst.merkleLayers[i] = make([][]byte, len(layer)) - for j, content := range layer { - dst.merkleLayers[i][j] = make([]byte, len(content)) - copy(dst.merkleLayers[i][j], content) - } - } - } - - state.StateCount.Inc() - // Finalizer runs when dst is being destroyed in garbage collection. - runtime.SetFinalizer(dst, func(b *BeaconState) { - for field, v := range b.sharedFieldReferences { - v.MinusRef() - if b.stateFieldLeaves[field].FieldReference() != nil { - b.stateFieldLeaves[field].FieldReference().MinusRef() - } - - } - for i := 0; i < fieldCount; i++ { - field := types.FieldIndex(i) - delete(b.stateFieldLeaves, field) - delete(b.dirtyIndices, field) - delete(b.dirtyFields, field) - delete(b.sharedFieldReferences, field) - delete(b.stateFieldLeaves, field) - } - state.StateCount.Sub(1) - }) - return dst -} - -// HashTreeRoot of the beacon state retrieves the Merkle root of the trie -// representation of the beacon state based on the Ethereum Simple Serialize specification. -func (b *BeaconState) HashTreeRoot(ctx context.Context) ([32]byte, error) { - ctx, span := trace.StartSpan(ctx, "beaconState.HashTreeRoot") - defer span.End() - - b.lock.Lock() - defer b.lock.Unlock() - if err := b.initializeMerkleLayers(ctx); err != nil { - return [32]byte{}, err - } - if err := b.recomputeDirtyFields(ctx); err != nil { - return [32]byte{}, err - } - return bytesutil.ToBytes32(b.merkleLayers[len(b.merkleLayers)-1][0]), nil -} - -// Initializes the Merkle layers for the beacon state if they are empty. -// WARNING: Caller must acquire the mutex before using. -func (b *BeaconState) initializeMerkleLayers(ctx context.Context) error { - if len(b.merkleLayers) > 0 { - return nil - } - protoState, ok := b.ToProtoUnsafe().(*ethpb.BeaconState) - if !ok { - return errors.New("state is of the wrong type") - } - fieldRoots, err := computeFieldRoots(ctx, protoState) - if err != nil { - return err - } - layers := stateutil.Merkleize(fieldRoots) - b.merkleLayers = layers - b.dirtyFields = make(map[types.FieldIndex]bool, params.BeaconConfig().BeaconStateFieldCount) - return nil -} - -// Recomputes the Merkle layers for the dirty fields in the state. -// WARNING: Caller must acquire the mutex before using. -func (b *BeaconState) recomputeDirtyFields(ctx context.Context) error { - for field := range b.dirtyFields { - root, err := b.rootSelector(ctx, field) - if err != nil { - return err - } - b.merkleLayers[0][field] = root[:] - b.recomputeRoot(int(field)) - delete(b.dirtyFields, field) - } - return nil -} - -// FieldReferencesCount returns the reference count held by each field. This -// also includes the field trie held by each field. -func (b *BeaconState) FieldReferencesCount() map[string]uint64 { - refMap := make(map[string]uint64) - b.lock.RLock() - defer b.lock.RUnlock() - for i, f := range b.sharedFieldReferences { - refMap[i.String(b.Version())] = uint64(f.Refs()) - } - for i, f := range b.stateFieldLeaves { - numOfRefs := uint64(f.FieldReference().Refs()) - f.RLock() - if !f.Empty() { - refMap[i.String(b.Version())+"_trie"] = numOfRefs - } - f.RUnlock() - } - return refMap -} - -// IsNil checks if the state and the underlying proto -// object are nil. -func (b *BeaconState) IsNil() bool { - return b == nil -} - -func (b *BeaconState) rootSelector(ctx context.Context, field types.FieldIndex) ([32]byte, error) { - _, span := trace.StartSpan(ctx, "beaconState.rootSelector") - defer span.End() - span.AddAttributes(trace.StringAttribute("field", field.String(b.Version()))) - - hasher := hash.CustomSHA256Hasher() - switch field { - case genesisTime: - return ssz.Uint64Root(b.genesisTime), nil - case genesisValidatorsRoot: - return b.genesisValidatorsRoot, nil - case slot: - return ssz.Uint64Root(uint64(b.slot)), nil - case eth1DepositIndex: - return ssz.Uint64Root(b.eth1DepositIndex), nil - case fork: - return ssz.ForkRoot(b.fork) - case latestBlockHeader: - return stateutil.BlockHeaderRoot(b.latestBlockHeader) - case blockRoots: - if b.rebuildTrie[field] { - err := b.resetFieldTrie(field, b.blockRoots, fieldparams.BlockRootsLength) - if err != nil { - return [32]byte{}, err - } - delete(b.rebuildTrie, field) - return b.stateFieldLeaves[field].TrieRoot() - } - return b.recomputeFieldTrie(blockRoots, b.blockRoots) - case stateRoots: - if b.rebuildTrie[field] { - err := b.resetFieldTrie(field, b.stateRoots, fieldparams.StateRootsLength) - if err != nil { - return [32]byte{}, err - } - delete(b.rebuildTrie, field) - return b.stateFieldLeaves[field].TrieRoot() - } - return b.recomputeFieldTrie(stateRoots, b.stateRoots) - case historicalRoots: - hRoots := make([][]byte, len(b.historicalRoots)) - for i := range hRoots { - hRoots[i] = b.historicalRoots[i][:] - } - return ssz.ByteArrayRootWithLimit(hRoots, fieldparams.HistoricalRootsLength) - case eth1Data: - return stateutil.Eth1Root(hasher, b.eth1Data) - case eth1DataVotes: - if b.rebuildTrie[field] { - err := b.resetFieldTrie( - field, - b.eth1DataVotes, - fieldparams.Eth1DataVotesLength, - ) - if err != nil { - return [32]byte{}, err - } - delete(b.rebuildTrie, field) - return b.stateFieldLeaves[field].TrieRoot() - } - return b.recomputeFieldTrie(field, b.eth1DataVotes) - case validators: - if b.rebuildTrie[field] { - err := b.resetFieldTrie(field, b.validators, fieldparams.ValidatorRegistryLimit) - if err != nil { - return [32]byte{}, err - } - delete(b.rebuildTrie, validators) - return b.stateFieldLeaves[field].TrieRoot() - } - return b.recomputeFieldTrie(validators, b.validators) - case balances: - if b.rebuildTrie[field] { - maxBalCap := uint64(fieldparams.ValidatorRegistryLimit) - elemSize := uint64(8) - balLimit := (maxBalCap*elemSize + 31) / 32 - err := b.resetFieldTrie(field, b.balances, balLimit) - if err != nil { - return [32]byte{}, err - } - delete(b.rebuildTrie, field) - return b.stateFieldLeaves[field].TrieRoot() - } - return b.recomputeFieldTrie(balances, b.balances) - case randaoMixes: - if b.rebuildTrie[field] { - err := b.resetFieldTrie(field, b.randaoMixes, fieldparams.RandaoMixesLength) - if err != nil { - return [32]byte{}, err - } - delete(b.rebuildTrie, field) - return b.stateFieldLeaves[field].TrieRoot() - } - return b.recomputeFieldTrie(randaoMixes, b.randaoMixes) - case slashings: - return ssz.SlashingsRoot(b.slashings) - case previousEpochAttestations: - if b.rebuildTrie[field] { - err := b.resetFieldTrie( - field, - b.previousEpochAttestations, - fieldparams.PreviousEpochAttestationsLength, - ) - if err != nil { - return [32]byte{}, err - } - delete(b.rebuildTrie, field) - return b.stateFieldLeaves[field].TrieRoot() - } - return b.recomputeFieldTrie(field, b.previousEpochAttestations) - case currentEpochAttestations: - if b.rebuildTrie[field] { - err := b.resetFieldTrie( - field, - b.currentEpochAttestations, - fieldparams.CurrentEpochAttestationsLength, - ) - if err != nil { - return [32]byte{}, err - } - delete(b.rebuildTrie, field) - return b.stateFieldLeaves[field].TrieRoot() - } - return b.recomputeFieldTrie(field, b.currentEpochAttestations) - case justificationBits: - return bytesutil.ToBytes32(b.justificationBits), nil - case previousJustifiedCheckpoint: - return ssz.CheckpointRoot(hasher, b.previousJustifiedCheckpoint) - case currentJustifiedCheckpoint: - return ssz.CheckpointRoot(hasher, b.currentJustifiedCheckpoint) - case finalizedCheckpoint: - return ssz.CheckpointRoot(hasher, b.finalizedCheckpoint) - } - return [32]byte{}, errors.New("invalid field index provided") -} - -func (b *BeaconState) recomputeFieldTrie(index types.FieldIndex, elements interface{}) ([32]byte, error) { - fTrie := b.stateFieldLeaves[index] - // We can't lock the trie directly because the trie's variable gets reassigned, - // and therefore we would call Unlock() on a different object. - fTrieMutex := fTrie.RWMutex - if fTrie.FieldReference().Refs() > 1 { - fTrieMutex.Lock() - fTrie.FieldReference().MinusRef() - newTrie := fTrie.CopyTrie() - b.stateFieldLeaves[index] = newTrie - fTrie = newTrie - fTrieMutex.Unlock() - } - // remove duplicate indexes - b.dirtyIndices[index] = slice.SetUint64(b.dirtyIndices[index]) - // sort indexes again - sort.Slice(b.dirtyIndices[index], func(i int, j int) bool { - return b.dirtyIndices[index][i] < b.dirtyIndices[index][j] - }) - root, err := fTrie.RecomputeTrie(b.dirtyIndices[index], elements) - if err != nil { - return [32]byte{}, err - } - b.dirtyIndices[index] = []uint64{} - return root, nil -} - -func (b *BeaconState) resetFieldTrie(index types.FieldIndex, elements interface{}, length uint64) error { - fTrie, err := fieldtrie.NewFieldTrie(index, fieldMap[index], elements, length) - if err != nil { - return err - } - b.stateFieldLeaves[index] = fTrie - b.dirtyIndices[index] = []uint64{} - return nil -} diff --git a/beacon-chain/state/state-native/v1/types.go b/beacon-chain/state/state-native/v1/types.go deleted file mode 100644 index 224322840c..0000000000 --- a/beacon-chain/state/state-native/v1/types.go +++ /dev/null @@ -1,54 +0,0 @@ -package v1 - -import ( - "github.com/prysmaticlabs/prysm/beacon-chain/state" - "github.com/prysmaticlabs/prysm/beacon-chain/state/types" - "github.com/prysmaticlabs/prysm/config/params" -) - -// Ensure type BeaconState below implements BeaconState interface. -var _ state.BeaconState = (*BeaconState)(nil) - -func init() { - fieldMap = make(map[types.FieldIndex]types.DataType, params.BeaconConfig().BeaconStateFieldCount) - // Initialize the fixed sized arrays. - fieldMap[types.BlockRoots] = types.BasicArray - fieldMap[types.StateRoots] = types.BasicArray - fieldMap[types.RandaoMixes] = types.BasicArray - - // Initialize the composite arrays. - fieldMap[types.Eth1DataVotes] = types.CompositeArray - fieldMap[types.Validators] = types.CompositeArray - fieldMap[types.PreviousEpochAttestations] = types.CompositeArray - fieldMap[types.CurrentEpochAttestations] = types.CompositeArray - fieldMap[types.Balances] = types.CompressedArray -} - -// fieldMap keeps track of each field -// to its corresponding data type. -var fieldMap map[types.FieldIndex]types.DataType - -// Field Aliases for values from the types package. -const ( - genesisTime = types.GenesisTime - genesisValidatorsRoot = types.GenesisValidatorsRoot - slot = types.Slot - fork = types.Fork - latestBlockHeader = types.LatestBlockHeader - blockRoots = types.BlockRoots - stateRoots = types.StateRoots - historicalRoots = types.HistoricalRoots - eth1Data = types.Eth1Data - eth1DataVotes = types.Eth1DataVotes - eth1DepositIndex = types.Eth1DepositIndex - validators = types.Validators - balances = types.Balances - randaoMixes = types.RandaoMixes - slashings = types.Slashings - previousEpochAttestations = types.PreviousEpochAttestations - currentEpochAttestations = types.CurrentEpochAttestations - justificationBits = types.JustificationBits - previousJustifiedCheckpoint = types.PreviousJustifiedCheckpoint - currentJustifiedCheckpoint = types.CurrentJustifiedCheckpoint - finalizedCheckpoint = types.FinalizedCheckpoint -) diff --git a/beacon-chain/state/state-native/v1/unsupported_getters.go b/beacon-chain/state/state-native/v1/unsupported_getters.go deleted file mode 100644 index 3717aab456..0000000000 --- a/beacon-chain/state/state-native/v1/unsupported_getters.go +++ /dev/null @@ -1,36 +0,0 @@ -package v1 - -import ( - "github.com/pkg/errors" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -// CurrentEpochParticipation is not supported for phase 0 beacon state. -func (*BeaconState) CurrentEpochParticipation() ([]byte, error) { - return nil, errors.New("CurrentEpochParticipation is not supported for phase 0 beacon state") -} - -// PreviousEpochParticipation is not supported for phase 0 beacon state. -func (*BeaconState) PreviousEpochParticipation() ([]byte, error) { - return nil, errors.New("PreviousEpochParticipation is not supported for phase 0 beacon state") -} - -// InactivityScores is not supported for phase 0 beacon state. -func (*BeaconState) InactivityScores() ([]uint64, error) { - return nil, errors.New("InactivityScores is not supported for phase 0 beacon state") -} - -// CurrentSyncCommittee is not supported for phase 0 beacon state. -func (*BeaconState) CurrentSyncCommittee() (*ethpb.SyncCommittee, error) { - return nil, errors.New("CurrentSyncCommittee is not supported for phase 0 beacon state") -} - -// NextSyncCommittee is not supported for phase 0 beacon state. -func (*BeaconState) NextSyncCommittee() (*ethpb.SyncCommittee, error) { - return nil, errors.New("NextSyncCommittee is not supported for phase 0 beacon state") -} - -// LatestExecutionPayloadHeader is not supported for phase 0 beacon state. -func (*BeaconState) LatestExecutionPayloadHeader() (*ethpb.ExecutionPayloadHeader, error) { - return nil, errors.New("LatestExecutionPayloadHeader is not supported for phase 0 beacon state") -} diff --git a/beacon-chain/state/state-native/v1/unsupported_setters.go b/beacon-chain/state/state-native/v1/unsupported_setters.go deleted file mode 100644 index 242d08834a..0000000000 --- a/beacon-chain/state/state-native/v1/unsupported_setters.go +++ /dev/null @@ -1,61 +0,0 @@ -package v1 - -import ( - "github.com/pkg/errors" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -// AppendCurrentParticipationBits is not supported for phase 0 beacon state. -func (*BeaconState) AppendCurrentParticipationBits(_ byte) error { - return errors.New("AppendCurrentParticipationBits is not supported for phase 0 beacon state") -} - -// AppendPreviousParticipationBits is not supported for phase 0 beacon state. -func (*BeaconState) AppendPreviousParticipationBits(_ byte) error { - return errors.New("AppendPreviousParticipationBits is not supported for phase 0 beacon state") -} - -// AppendInactivityScore is not supported for phase 0 beacon state. -func (*BeaconState) AppendInactivityScore(_ uint64) error { - return errors.New("AppendInactivityScore is not supported for phase 0 beacon state") -} - -// SetCurrentSyncCommittee is not supported for phase 0 beacon state. -func (*BeaconState) SetCurrentSyncCommittee(_ *ethpb.SyncCommittee) error { - return errors.New("SetCurrentSyncCommittee is not supported for phase 0 beacon state") -} - -// SetNextSyncCommittee is not supported for phase 0 beacon state. -func (*BeaconState) SetNextSyncCommittee(_ *ethpb.SyncCommittee) error { - return errors.New("SetNextSyncCommittee is not supported for phase 0 beacon state") -} - -// SetPreviousParticipationBits is not supported for phase 0 beacon state. -func (*BeaconState) SetPreviousParticipationBits(_ []byte) error { - return errors.New("SetPreviousParticipationBits is not supported for phase 0 beacon state") -} - -// SetCurrentParticipationBits is not supported for phase 0 beacon state. -func (*BeaconState) SetCurrentParticipationBits(_ []byte) error { - return errors.New("SetCurrentParticipationBits is not supported for phase 0 beacon state") -} - -// ModifyPreviousParticipationBits is not supported for phase 0 beacon state. -func (b *BeaconState) ModifyPreviousParticipationBits(mutator func(val []byte) ([]byte, error)) error { - return errors.New("ModifyPreviousParticipationBits is not supported for phase 0 beacon state") -} - -// ModifyCurrentParticipationBits is not supported for phase 0 beacon state. -func (b *BeaconState) ModifyCurrentParticipationBits(mutator func(val []byte) ([]byte, error)) error { - return errors.New("ModifyCurrentParticipationBits is not supported for phase 0 beacon state") -} - -// SetInactivityScores is not supported for phase 0 beacon state. -func (*BeaconState) SetInactivityScores(_ []uint64) error { - return errors.New("SetInactivityScores is not supported for phase 0 beacon state") -} - -// SetLatestExecutionPayloadHeader is not supported for phase 0 beacon state. -func (*BeaconState) SetLatestExecutionPayloadHeader(val *ethpb.ExecutionPayloadHeader) error { - return errors.New("SetLatestExecutionPayloadHeader is not supported for phase 0 beacon state") -} diff --git a/beacon-chain/state/state-native/v2/BUILD.bazel b/beacon-chain/state/state-native/v2/BUILD.bazel deleted file mode 100644 index 0867be46cf..0000000000 --- a/beacon-chain/state/state-native/v2/BUILD.bazel +++ /dev/null @@ -1,119 +0,0 @@ -load("@prysm//tools/go:def.bzl", "go_library", "go_test") -load("//proto:ssz_proto_library.bzl", "ssz_proto_files") -load("//tools:ssz.bzl", "SSZ_DEPS", "ssz_gen_marshal") - -go_library( - name = "go_default_library", - srcs = [ - "deprecated_getters.go", - "deprecated_setters.go", - "field_roots.go", - "getters_block.go", - "getters_checkpoint.go", - "getters_eth1.go", - "getters_misc.go", - "getters_participation.go", - "getters_randao.go", - "getters_state.go", - "getters_sync_committee.go", - "getters_validator.go", - "proofs.go", - "setters_block.go", - "setters_checkpoint.go", - "setters_eth1.go", - "setters_misc.go", - "setters_participation.go", - "setters_randao.go", - "setters_state.go", - "setters_sync_committee.go", - "setters_validator.go", - "state_trie.go", - "types.go", - ":ssz_generated_files", # keep - ] + select({ - "//config:mainnet": ["beacon_state_mainnet.go"], - "//config:minimal": ["beacon_state_minimal.go"], - }), - importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/v2", - visibility = [ - "//beacon-chain:__subpackages__", - "//proto/migration:__subpackages__", - "//testing/spectest:__subpackages__", - "//testing/util:__pkg__", - ], - deps = [ - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/fieldtrie:go_default_library", - "//beacon-chain/state/state-native/custom-types:go_default_library", - "//beacon-chain/state/state-native/v1:go_default_library", - "//beacon-chain/state/stateutil:go_default_library", - "//beacon-chain/state/types:go_default_library", - "//config/fieldparams:go_default_library", - "//config/params:go_default_library", - "//consensus-types/primitives:go_default_library", - "//container/slice:go_default_library", - "//crypto/hash:go_default_library", - "//encoding/bytesutil:go_default_library", - "//encoding/ssz:go_default_library", - "//proto/prysm/v1alpha1:go_default_library", - "//runtime/version:go_default_library", - "@com_github_ferranbt_fastssz//:go_default_library", - "@com_github_pkg_errors//:go_default_library", - "@com_github_prysmaticlabs_go_bitfield//:go_default_library", - "@io_opencensus_go//trace:go_default_library", - "@org_golang_google_protobuf//proto:go_default_library", - ], -) - -go_test( - name = "go_default_test", - srcs = [ - "deprecated_getters_test.go", - "deprecated_setters_test.go", - "getters_block_test.go", - "getters_test.go", - "getters_validator_test.go", - "proofs_test.go", - "setters_test.go", - "state_trie_test.go", - ] + select({ - "//config:mainnet": ["beacon_state_mainnet_test.go"], - "//config:minimal": ["beacon_state_minimal_test.go"], - }), - embed = [":go_default_library"], - deps = [ - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/stateutil:go_default_library", - "//beacon-chain/state/testing:go_default_library", - "//beacon-chain/state/types:go_default_library", - "//beacon-chain/state/v2:go_default_library", - "//config/fieldparams:go_default_library", - "//config/params:go_default_library", - "//consensus-types/primitives:go_default_library", - "//container/trie:go_default_library", - "//crypto/bls:go_default_library", - "//encoding/bytesutil:go_default_library", - "//proto/prysm/v1alpha1:go_default_library", - "//testing/assert:go_default_library", - "//testing/require:go_default_library", - "//testing/util:go_default_library", - "@com_github_prysmaticlabs_go_bitfield//:go_default_library", - ], -) - -ssz_gen_marshal( - name = "ssz_generated_files", - srcs = select({ - "//config:mainnet": ["beacon_state_mainnet.go"], - "//config:minimal": ["beacon_state_minimal.go"], - }), - includes = [ - "//beacon-chain/state/state-native/custom-types:go_default_library", - "//config/fieldparams:go_default_library", - "//consensus-types/primitives:go_default_library", - "//proto/prysm/v1alpha1:go_default_library", - ], - objs = [ - "BeaconState[no-htr]", - ], -) diff --git a/beacon-chain/state/state-native/v2/beacon_state_mainnet.go b/beacon-chain/state/state-native/v2/beacon_state_mainnet.go deleted file mode 100644 index dbb95495ec..0000000000 --- a/beacon-chain/state/state-native/v2/beacon_state_mainnet.go +++ /dev/null @@ -1,54 +0,0 @@ -//go:build !minimal -// +build !minimal - -package v2 - -import ( - "sync" - - "github.com/prysmaticlabs/go-bitfield" - "github.com/prysmaticlabs/prysm/beacon-chain/state/fieldtrie" - customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - "github.com/prysmaticlabs/prysm/beacon-chain/state/types" - eth2types "github.com/prysmaticlabs/prysm/consensus-types/primitives" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -// BeaconState defines a struct containing utilities for the eth2 chain state, defining -// getters and setters for its respective values and helpful functions such as HashTreeRoot(). -type BeaconState struct { - genesisTime uint64 `ssz-gen:"true"` - genesisValidatorsRoot customtypes.Byte32 `ssz-gen:"true" ssz-size:"32"` - slot eth2types.Slot `ssz-gen:"true"` - fork *ethpb.Fork `ssz-gen:"true"` - latestBlockHeader *ethpb.BeaconBlockHeader `ssz-gen:"true"` - blockRoots *customtypes.BlockRoots `ssz-gen:"true" ssz-size:"8192,32"` - stateRoots *customtypes.StateRoots `ssz-gen:"true" ssz-size:"8192,32"` - historicalRoots customtypes.HistoricalRoots `ssz-gen:"true" ssz-size:"?,32" ssz-max:"16777216"` - eth1Data *ethpb.Eth1Data `ssz-gen:"true"` - eth1DataVotes []*ethpb.Eth1Data `ssz-gen:"true" ssz-max:"2048"` - eth1DepositIndex uint64 `ssz-gen:"true"` - validators []*ethpb.Validator `ssz-gen:"true" ssz-max:"1099511627776"` - balances []uint64 `ssz-gen:"true" ssz-max:"1099511627776"` - randaoMixes *customtypes.RandaoMixes `ssz-gen:"true" ssz-size:"65536,32"` - slashings []uint64 `ssz-gen:"true" ssz-size:"8192"` - previousEpochParticipation []byte `ssz-gen:"true" ssz-max:"1099511627776"` - currentEpochParticipation []byte `ssz-gen:"true" ssz-max:"1099511627776"` - justificationBits bitfield.Bitvector4 `ssz-gen:"true" ssz-size:"1"` - previousJustifiedCheckpoint *ethpb.Checkpoint `ssz-gen:"true"` - currentJustifiedCheckpoint *ethpb.Checkpoint `ssz-gen:"true"` - finalizedCheckpoint *ethpb.Checkpoint `ssz-gen:"true"` - inactivityScores []uint64 `ssz-gen:"true" ssz-max:"1099511627776"` - currentSyncCommittee *ethpb.SyncCommittee `ssz-gen:"true"` - nextSyncCommittee *ethpb.SyncCommittee `ssz-gen:"true"` - - lock sync.RWMutex - dirtyFields map[types.FieldIndex]bool - dirtyIndices map[types.FieldIndex][]uint64 - stateFieldLeaves map[types.FieldIndex]*fieldtrie.FieldTrie - rebuildTrie map[types.FieldIndex]bool - valMapHandler *stateutil.ValidatorMapHandler - merkleLayers [][][]byte - sharedFieldReferences map[types.FieldIndex]*stateutil.Reference -} diff --git a/beacon-chain/state/state-native/v2/beacon_state_mainnet_test.go b/beacon-chain/state/state-native/v2/beacon_state_mainnet_test.go deleted file mode 100644 index fd80e5c034..0000000000 --- a/beacon-chain/state/state-native/v2/beacon_state_mainnet_test.go +++ /dev/null @@ -1,87 +0,0 @@ -//go:build !minimal -// +build !minimal - -package v2 - -import ( - "reflect" - "strconv" - "testing" - - fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" - "github.com/prysmaticlabs/prysm/testing/assert" - "github.com/prysmaticlabs/prysm/testing/require" -) - -func TestMainnetSszValuesAgainstFieldParams(t *testing.T) { - // Casting needed to avoid lock copy analyzer issue. - bs := (interface{})(BeaconState{}) - bsType := reflect.TypeOf(bs) - - f, ok := bsType.FieldByName("genesisValidatorsRoot") - require.Equal(t, true, ok, "Required field not found") - v := f.Tag.Get("ssz-size") - assert.Equal(t, strconv.Itoa(fieldparams.RootLength), v) - - f, ok = bsType.FieldByName("blockRoots") - require.Equal(t, true, ok, "Required field not found") - v = f.Tag.Get("ssz-size") - assert.Equal(t, strconv.Itoa(fieldparams.BlockRootsLength)+","+strconv.Itoa(fieldparams.RootLength), v) - - f, ok = bsType.FieldByName("stateRoots") - require.Equal(t, true, ok, "Required field not found") - v = f.Tag.Get("ssz-size") - assert.Equal(t, strconv.Itoa(fieldparams.StateRootsLength)+","+strconv.Itoa(fieldparams.RootLength), v) - - f, ok = bsType.FieldByName("historicalRoots") - require.Equal(t, true, ok, "Required field not found") - v = f.Tag.Get("ssz-size") - assert.Equal(t, "?,"+strconv.Itoa(fieldparams.RootLength), v) - v = f.Tag.Get("ssz-max") - assert.Equal(t, strconv.Itoa(fieldparams.HistoricalRootsLength), v) - - f, ok = bsType.FieldByName("eth1DataVotes") - require.Equal(t, true, ok, "Required field not found") - v = f.Tag.Get("ssz-max") - assert.Equal(t, strconv.Itoa(fieldparams.Eth1DataVotesLength), v) - - f, ok = bsType.FieldByName("validators") - require.Equal(t, true, ok, "Required field not found") - v = f.Tag.Get("ssz-max") - assert.Equal(t, strconv.Itoa(fieldparams.ValidatorRegistryLimit), v) - - f, ok = bsType.FieldByName("balances") - require.Equal(t, true, ok, "Required field not found") - v = f.Tag.Get("ssz-max") - assert.Equal(t, strconv.Itoa(fieldparams.ValidatorRegistryLimit), v) - - f, ok = bsType.FieldByName("randaoMixes") - require.Equal(t, true, ok, "Required field not found") - v = f.Tag.Get("ssz-size") - assert.Equal(t, strconv.Itoa(fieldparams.RandaoMixesLength)+","+strconv.Itoa(fieldparams.RootLength), v) - - f, ok = bsType.FieldByName("slashings") - require.Equal(t, true, ok, "Required field not found") - v = f.Tag.Get("ssz-size") - assert.Equal(t, strconv.Itoa(fieldparams.SlashingsLength), v) - - f, ok = bsType.FieldByName("previousEpochParticipation") - require.Equal(t, true, ok, "Required field not found") - v = f.Tag.Get("ssz-max") - assert.Equal(t, strconv.Itoa(fieldparams.ValidatorRegistryLimit), v) - - f, ok = bsType.FieldByName("currentEpochParticipation") - require.Equal(t, true, ok, "Required field not found") - v = f.Tag.Get("ssz-max") - assert.Equal(t, strconv.Itoa(fieldparams.ValidatorRegistryLimit), v) - - f, ok = bsType.FieldByName("justificationBits") - require.Equal(t, true, ok, "Required field not found") - v = f.Tag.Get("ssz-size") - assert.Equal(t, "1", v) - - f, ok = bsType.FieldByName("inactivityScores") - require.Equal(t, true, ok, "Required field not found") - v = f.Tag.Get("ssz-max") - assert.Equal(t, strconv.Itoa(fieldparams.ValidatorRegistryLimit), v) -} diff --git a/beacon-chain/state/state-native/v2/beacon_state_minimal.go b/beacon-chain/state/state-native/v2/beacon_state_minimal.go deleted file mode 100644 index 26b2c60497..0000000000 --- a/beacon-chain/state/state-native/v2/beacon_state_minimal.go +++ /dev/null @@ -1,54 +0,0 @@ -//go:build minimal -// +build minimal - -package v2 - -import ( - "sync" - - "github.com/prysmaticlabs/go-bitfield" - "github.com/prysmaticlabs/prysm/beacon-chain/state/fieldtrie" - customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - "github.com/prysmaticlabs/prysm/beacon-chain/state/types" - eth2types "github.com/prysmaticlabs/prysm/consensus-types/primitives" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -// BeaconState defines a struct containing utilities for the eth2 chain state, defining -// getters and setters for its respective values and helpful functions such as HashTreeRoot(). -type BeaconState struct { - genesisTime uint64 `ssz-gen:"true"` - genesisValidatorsRoot customtypes.Byte32 `ssz-gen:"true" ssz-size:"32"` - slot eth2types.Slot `ssz-gen:"true"` - fork *ethpb.Fork `ssz-gen:"true"` - latestBlockHeader *ethpb.BeaconBlockHeader `ssz-gen:"true"` - blockRoots *customtypes.BlockRoots `ssz-gen:"true" ssz-size:"64,32"` - stateRoots *customtypes.StateRoots `ssz-gen:"true" ssz-size:"64,32"` - historicalRoots customtypes.HistoricalRoots `ssz-gen:"true" ssz-size:"?,32" ssz-max:"16777216"` - eth1Data *ethpb.Eth1Data `ssz-gen:"true"` - eth1DataVotes []*ethpb.Eth1Data `ssz-gen:"true" ssz-max:"32"` - eth1DepositIndex uint64 `ssz-gen:"true"` - validators []*ethpb.Validator `ssz-gen:"true" ssz-max:"1099511627776"` - balances []uint64 `ssz-gen:"true" ssz-max:"1099511627776"` - randaoMixes *customtypes.RandaoMixes `ssz-gen:"true" ssz-size:"64,32"` - slashings []uint64 `ssz-gen:"true" ssz-size:"64"` - previousEpochParticipation []byte `ssz-gen:"true" ssz-max:"1099511627776"` - currentEpochParticipation []byte `ssz-gen:"true" ssz-max:"1099511627776"` - justificationBits bitfield.Bitvector4 `ssz-gen:"true" ssz-size:"1"` - previousJustifiedCheckpoint *ethpb.Checkpoint `ssz-gen:"true"` - currentJustifiedCheckpoint *ethpb.Checkpoint `ssz-gen:"true"` - finalizedCheckpoint *ethpb.Checkpoint `ssz-gen:"true"` - inactivityScores []uint64 `ssz-gen:"true" ssz-max:"1099511627776"` - currentSyncCommittee *ethpb.SyncCommittee `ssz-gen:"true"` - nextSyncCommittee *ethpb.SyncCommittee `ssz-gen:"true"` - - lock sync.RWMutex - dirtyFields map[types.FieldIndex]bool - dirtyIndices map[types.FieldIndex][]uint64 - stateFieldLeaves map[types.FieldIndex]*fieldtrie.FieldTrie - rebuildTrie map[types.FieldIndex]bool - valMapHandler *stateutil.ValidatorMapHandler - merkleLayers [][][]byte - sharedFieldReferences map[types.FieldIndex]*stateutil.Reference -} diff --git a/beacon-chain/state/state-native/v2/beacon_state_minimal_test.go b/beacon-chain/state/state-native/v2/beacon_state_minimal_test.go deleted file mode 100644 index e2bf3c4a47..0000000000 --- a/beacon-chain/state/state-native/v2/beacon_state_minimal_test.go +++ /dev/null @@ -1,87 +0,0 @@ -//go:build minimal -// +build minimal - -package v2 - -import ( - "reflect" - "strconv" - "testing" - - fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" - "github.com/prysmaticlabs/prysm/testing/assert" - "github.com/prysmaticlabs/prysm/testing/require" -) - -func TestMinimalSszValuesAgainstFieldParams(t *testing.T) { - // Casting needed to avoid lock copy analyzer issue. - bs := (interface{})(BeaconState{}) - bsType := reflect.TypeOf(bs) - - f, ok := bsType.FieldByName("genesisValidatorsRoot") - require.Equal(t, true, ok, "Required field not found") - v := f.Tag.Get("ssz-size") - assert.Equal(t, strconv.Itoa(fieldparams.RootLength), v) - - f, ok = bsType.FieldByName("blockRoots") - require.Equal(t, true, ok, "Required field not found") - v = f.Tag.Get("ssz-size") - assert.Equal(t, strconv.Itoa(fieldparams.BlockRootsLength)+","+strconv.Itoa(fieldparams.RootLength), v) - - f, ok = bsType.FieldByName("stateRoots") - require.Equal(t, true, ok, "Required field not found") - v = f.Tag.Get("ssz-size") - assert.Equal(t, strconv.Itoa(fieldparams.StateRootsLength)+","+strconv.Itoa(fieldparams.RootLength), v) - - f, ok = bsType.FieldByName("historicalRoots") - require.Equal(t, true, ok, "Required field not found") - v = f.Tag.Get("ssz-size") - assert.Equal(t, "?,"+strconv.Itoa(fieldparams.RootLength), v) - v = f.Tag.Get("ssz-max") - assert.Equal(t, strconv.Itoa(fieldparams.HistoricalRootsLength), v) - - f, ok = bsType.FieldByName("eth1DataVotes") - require.Equal(t, true, ok, "Required field not found") - v = f.Tag.Get("ssz-max") - assert.Equal(t, strconv.Itoa(fieldparams.Eth1DataVotesLength), v) - - f, ok = bsType.FieldByName("validators") - require.Equal(t, true, ok, "Required field not found") - v = f.Tag.Get("ssz-max") - assert.Equal(t, strconv.Itoa(fieldparams.ValidatorRegistryLimit), v) - - f, ok = bsType.FieldByName("balances") - require.Equal(t, true, ok, "Required field not found") - v = f.Tag.Get("ssz-max") - assert.Equal(t, strconv.Itoa(fieldparams.ValidatorRegistryLimit), v) - - f, ok = bsType.FieldByName("randaoMixes") - require.Equal(t, true, ok, "Required field not found") - v = f.Tag.Get("ssz-size") - assert.Equal(t, strconv.Itoa(fieldparams.RandaoMixesLength)+","+strconv.Itoa(fieldparams.RootLength), v) - - f, ok = bsType.FieldByName("slashings") - require.Equal(t, true, ok, "Required field not found") - v = f.Tag.Get("ssz-size") - assert.Equal(t, strconv.Itoa(fieldparams.SlashingsLength), v) - - f, ok = bsType.FieldByName("previousEpochParticipation") - require.Equal(t, true, ok, "Required field not found") - v = f.Tag.Get("ssz-max") - assert.Equal(t, strconv.Itoa(fieldparams.ValidatorRegistryLimit), v) - - f, ok = bsType.FieldByName("currentEpochParticipation") - require.Equal(t, true, ok, "Required field not found") - v = f.Tag.Get("ssz-max") - assert.Equal(t, strconv.Itoa(fieldparams.ValidatorRegistryLimit), v) - - f, ok = bsType.FieldByName("justificationBits") - require.Equal(t, true, ok, "Required field not found") - v = f.Tag.Get("ssz-size") - assert.Equal(t, "1", v) - - f, ok = bsType.FieldByName("inactivityScores") - require.Equal(t, true, ok, "Required field not found") - v = f.Tag.Get("ssz-max") - assert.Equal(t, strconv.Itoa(fieldparams.ValidatorRegistryLimit), v) -} diff --git a/beacon-chain/state/state-native/v2/deprecated_getters.go b/beacon-chain/state/state-native/v2/deprecated_getters.go deleted file mode 100644 index 2257b577e8..0000000000 --- a/beacon-chain/state/state-native/v2/deprecated_getters.go +++ /dev/null @@ -1,21 +0,0 @@ -package v2 - -import ( - "github.com/pkg/errors" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -// PreviousEpochAttestations is not supported for HF1 beacon state. -func (*BeaconState) PreviousEpochAttestations() ([]*ethpb.PendingAttestation, error) { - return nil, errors.New("PreviousEpochAttestations is not supported for hard fork 1 beacon state") -} - -// CurrentEpochAttestations is not supported for HF1 beacon state. -func (*BeaconState) CurrentEpochAttestations() ([]*ethpb.PendingAttestation, error) { - return nil, errors.New("CurrentEpochAttestations is not supported for hard fork 1 beacon state") -} - -// LatestExecutionPayloadHeader is not supported for hard fork 1 beacon state. -func (*BeaconState) LatestExecutionPayloadHeader() (*ethpb.ExecutionPayloadHeader, error) { - return nil, errors.New("LatestExecutionPayloadHeader is not supported for hard fork 1 beacon state") -} diff --git a/beacon-chain/state/state-native/v2/deprecated_getters_test.go b/beacon-chain/state/state-native/v2/deprecated_getters_test.go deleted file mode 100644 index 6e4aafe62d..0000000000 --- a/beacon-chain/state/state-native/v2/deprecated_getters_test.go +++ /dev/null @@ -1,19 +0,0 @@ -package v2 - -import ( - "testing" - - "github.com/prysmaticlabs/prysm/testing/require" -) - -func TestBeaconState_CurrentEpochAttestations(t *testing.T) { - s := &BeaconState{} - _, err := s.CurrentEpochAttestations() - require.ErrorContains(t, "CurrentEpochAttestations is not supported for hard fork 1 beacon state", err) -} - -func TestBeaconState_PreviousEpochAttestations(t *testing.T) { - s := &BeaconState{} - _, err := s.PreviousEpochAttestations() - require.ErrorContains(t, "PreviousEpochAttestations is not supported for hard fork 1 beacon state", err) -} diff --git a/beacon-chain/state/state-native/v2/deprecated_setters.go b/beacon-chain/state/state-native/v2/deprecated_setters.go deleted file mode 100644 index 449bb82098..0000000000 --- a/beacon-chain/state/state-native/v2/deprecated_setters.go +++ /dev/null @@ -1,36 +0,0 @@ -package v2 - -import ( - "github.com/pkg/errors" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -// SetPreviousEpochAttestations is not supported for HF1 beacon state. -func (*BeaconState) SetPreviousEpochAttestations(_ []*ethpb.PendingAttestation) error { - return errors.New("SetPreviousEpochAttestations is not supported for hard fork 1 beacon state") -} - -// SetCurrentEpochAttestations is not supported for HF1 beacon state. -func (*BeaconState) SetCurrentEpochAttestations(_ []*ethpb.PendingAttestation) error { - return errors.New("SetCurrentEpochAttestations is not supported for hard fork 1 beacon state") -} - -// AppendCurrentEpochAttestations is not supported for HF1 beacon state. -func (*BeaconState) AppendCurrentEpochAttestations(_ *ethpb.PendingAttestation) error { - return errors.New("AppendCurrentEpochAttestations is not supported for hard fork 1 beacon state") -} - -// AppendPreviousEpochAttestations is not supported for HF1 beacon state. -func (*BeaconState) AppendPreviousEpochAttestations(_ *ethpb.PendingAttestation) error { - return errors.New("AppendPreviousEpochAttestations is not supported for hard fork 1 beacon state") -} - -// RotateAttestations is not supported for HF1 beacon state. -func (*BeaconState) RotateAttestations() error { - return errors.New("RotateAttestations is not supported for hard fork 1 beacon state") -} - -// SetLatestExecutionPayloadHeader is not supported for hard fork 1 beacon state. -func (*BeaconState) SetLatestExecutionPayloadHeader(_ *ethpb.ExecutionPayloadHeader) error { - return errors.New("SetLatestExecutionPayloadHeader is not supported for hard fork 1 beacon state") -} diff --git a/beacon-chain/state/state-native/v2/deprecated_setters_test.go b/beacon-chain/state/state-native/v2/deprecated_setters_test.go deleted file mode 100644 index 718c4f07b1..0000000000 --- a/beacon-chain/state/state-native/v2/deprecated_setters_test.go +++ /dev/null @@ -1,27 +0,0 @@ -package v2 - -import ( - "testing" - - "github.com/prysmaticlabs/prysm/testing/require" -) - -func TestBeaconState_AppendCurrentEpochAttestations(t *testing.T) { - s := &BeaconState{} - require.ErrorContains(t, "AppendCurrentEpochAttestations is not supported for hard fork 1 beacon state", s.AppendCurrentEpochAttestations(nil)) -} - -func TestBeaconState_AppendPreviousEpochAttestations(t *testing.T) { - s := &BeaconState{} - require.ErrorContains(t, "AppendPreviousEpochAttestations is not supported for hard fork 1 beacon state", s.AppendPreviousEpochAttestations(nil)) -} - -func TestBeaconState_SetCurrentEpochAttestations(t *testing.T) { - s := &BeaconState{} - require.ErrorContains(t, "SetCurrentEpochAttestations is not supported for hard fork 1 beacon state", s.SetCurrentEpochAttestations(nil)) -} - -func TestBeaconState_SetPreviousEpochAttestations(t *testing.T) { - s := &BeaconState{} - require.ErrorContains(t, "SetPreviousEpochAttestations is not supported for hard fork 1 beacon state", s.SetPreviousEpochAttestations(nil)) -} diff --git a/beacon-chain/state/state-native/v2/field_roots.go b/beacon-chain/state/state-native/v2/field_roots.go deleted file mode 100644 index db62145ca1..0000000000 --- a/beacon-chain/state/state-native/v2/field_roots.go +++ /dev/null @@ -1,14 +0,0 @@ -package v2 - -import ( - "context" - - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -// computeFieldRoots returns the hash tree root computations of every field in -// the beacon state as a list of 32 byte roots. -func computeFieldRoots(ctx context.Context, state *ethpb.BeaconStateAltair) ([][]byte, error) { - return stateutil.ComputeFieldRootsWithHasherAltair(ctx, state) -} diff --git a/beacon-chain/state/state-native/v2/generated.ssz.go b/beacon-chain/state/state-native/v2/generated.ssz.go deleted file mode 100644 index df75cc778e..0000000000 --- a/beacon-chain/state/state-native/v2/generated.ssz.go +++ /dev/null @@ -1,505 +0,0 @@ -// Code generated by fastssz. DO NOT EDIT. -// Hash: 62b465df1ba19e36b9e8f7b16a383284350eb588bc459b4dd80f1b48ce9d7d64 -package v2 - -import ( - ssz "github.com/ferranbt/fastssz" - eth2types "github.com/prysmaticlabs/prysm/consensus-types/primitives" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -// MarshalSSZ ssz marshals the BeaconState object -func (b *BeaconState) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(b) -} - -// MarshalSSZTo ssz marshals the BeaconState object to a target array -func (b *BeaconState) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - offset := int(2736629) - - // Field (0) 'genesisTime' - dst = ssz.MarshalUint64(dst, b.genesisTime) - - // Field (1) 'genesisValidatorsRoot' - dst = append(dst, b.genesisValidatorsRoot[:]...) - - // Field (2) 'slot' - dst = ssz.MarshalUint64(dst, uint64(b.slot)) - - // Field (3) 'fork' - if b.fork == nil { - b.fork = new(ethpb.Fork) - } - if dst, err = b.fork.MarshalSSZTo(dst); err != nil { - return - } - - // Field (4) 'latestBlockHeader' - if b.latestBlockHeader == nil { - b.latestBlockHeader = new(ethpb.BeaconBlockHeader) - } - if dst, err = b.latestBlockHeader.MarshalSSZTo(dst); err != nil { - return - } - - // Field (5) 'blockRoots' - for ii := 0; ii < 8192; ii++ { - dst = append(dst, b.blockRoots[ii][:]...) - } - - // Field (6) 'stateRoots' - for ii := 0; ii < 8192; ii++ { - dst = append(dst, b.stateRoots[ii][:]...) - } - - // Offset (7) 'historicalRoots' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.historicalRoots) * 32 - - // Field (8) 'eth1Data' - if b.eth1Data == nil { - b.eth1Data = new(ethpb.Eth1Data) - } - if dst, err = b.eth1Data.MarshalSSZTo(dst); err != nil { - return - } - - // Offset (9) 'eth1DataVotes' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.eth1DataVotes) * 72 - - // Field (10) 'eth1DepositIndex' - dst = ssz.MarshalUint64(dst, b.eth1DepositIndex) - - // Offset (11) 'validators' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.validators) * 121 - - // Offset (12) 'balances' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.balances) * 8 - - // Field (13) 'randaoMixes' - for ii := 0; ii < 65536; ii++ { - dst = append(dst, b.randaoMixes[ii][:]...) - } - - // Field (14) 'slashings' - if len(b.slashings) != 8192 { - err = ssz.ErrVectorLength - return - } - for ii := 0; ii < 8192; ii++ { - dst = ssz.MarshalUint64(dst, b.slashings[ii]) - } - - // Offset (15) 'previousEpochParticipation' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.previousEpochParticipation) - - // Offset (16) 'currentEpochParticipation' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.currentEpochParticipation) - - // Field (17) 'justificationBits' - if len(b.justificationBits) != 1 { - err = ssz.ErrBytesLength - return - } - dst = append(dst, b.justificationBits...) - - // Field (18) 'previousJustifiedCheckpoint' - if b.previousJustifiedCheckpoint == nil { - b.previousJustifiedCheckpoint = new(ethpb.Checkpoint) - } - if dst, err = b.previousJustifiedCheckpoint.MarshalSSZTo(dst); err != nil { - return - } - - // Field (19) 'currentJustifiedCheckpoint' - if b.currentJustifiedCheckpoint == nil { - b.currentJustifiedCheckpoint = new(ethpb.Checkpoint) - } - if dst, err = b.currentJustifiedCheckpoint.MarshalSSZTo(dst); err != nil { - return - } - - // Field (20) 'finalizedCheckpoint' - if b.finalizedCheckpoint == nil { - b.finalizedCheckpoint = new(ethpb.Checkpoint) - } - if dst, err = b.finalizedCheckpoint.MarshalSSZTo(dst); err != nil { - return - } - - // Offset (21) 'inactivityScores' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.inactivityScores) * 8 - - // Field (22) 'currentSyncCommittee' - if b.currentSyncCommittee == nil { - b.currentSyncCommittee = new(ethpb.SyncCommittee) - } - if dst, err = b.currentSyncCommittee.MarshalSSZTo(dst); err != nil { - return - } - - // Field (23) 'nextSyncCommittee' - if b.nextSyncCommittee == nil { - b.nextSyncCommittee = new(ethpb.SyncCommittee) - } - if dst, err = b.nextSyncCommittee.MarshalSSZTo(dst); err != nil { - return - } - - // Field (7) 'historicalRoots' - if len(b.historicalRoots) > 16777216 { - err = ssz.ErrListTooBig - return - } - for ii := 0; ii < len(b.historicalRoots); ii++ { - dst = append(dst, b.historicalRoots[ii][:]...) - } - - // Field (9) 'eth1DataVotes' - if len(b.eth1DataVotes) > 2048 { - err = ssz.ErrListTooBig - return - } - for ii := 0; ii < len(b.eth1DataVotes); ii++ { - if dst, err = b.eth1DataVotes[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (11) 'validators' - if len(b.validators) > 1099511627776 { - err = ssz.ErrListTooBig - return - } - for ii := 0; ii < len(b.validators); ii++ { - if dst, err = b.validators[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (12) 'balances' - if len(b.balances) > 1099511627776 { - err = ssz.ErrListTooBig - return - } - for ii := 0; ii < len(b.balances); ii++ { - dst = ssz.MarshalUint64(dst, b.balances[ii]) - } - - // Field (15) 'previousEpochParticipation' - if len(b.previousEpochParticipation) > 1099511627776 { - err = ssz.ErrBytesLength - return - } - dst = append(dst, b.previousEpochParticipation...) - - // Field (16) 'currentEpochParticipation' - if len(b.currentEpochParticipation) > 1099511627776 { - err = ssz.ErrBytesLength - return - } - dst = append(dst, b.currentEpochParticipation...) - - // Field (21) 'inactivityScores' - if len(b.inactivityScores) > 1099511627776 { - err = ssz.ErrListTooBig - return - } - for ii := 0; ii < len(b.inactivityScores); ii++ { - dst = ssz.MarshalUint64(dst, b.inactivityScores[ii]) - } - - return -} - -// UnmarshalSSZ ssz unmarshals the BeaconState object -func (b *BeaconState) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size < 2736629 { - return ssz.ErrSize - } - - tail := buf - var o7, o9, o11, o12, o15, o16, o21 uint64 - - // Field (0) 'genesisTime' - b.genesisTime = ssz.UnmarshallUint64(buf[0:8]) - - // Field (1) 'genesisValidatorsRoot' - copy(b.genesisValidatorsRoot[:], buf[8:40]) - - // Field (2) 'slot' - b.slot = eth2types.Slot(ssz.UnmarshallUint64(buf[40:48])) - - // Field (3) 'fork' - if b.fork == nil { - b.fork = new(ethpb.Fork) - } - if err = b.fork.UnmarshalSSZ(buf[48:64]); err != nil { - return err - } - - // Field (4) 'latestBlockHeader' - if b.latestBlockHeader == nil { - b.latestBlockHeader = new(ethpb.BeaconBlockHeader) - } - if err = b.latestBlockHeader.UnmarshalSSZ(buf[64:176]); err != nil { - return err - } - - // Field (5) 'blockRoots' - - for ii := 0; ii < 8192; ii++ { - copy(b.blockRoots[ii][:], buf[176:262320][ii*32:(ii+1)*32]) - } - - // Field (6) 'stateRoots' - - for ii := 0; ii < 8192; ii++ { - copy(b.stateRoots[ii][:], buf[262320:524464][ii*32:(ii+1)*32]) - } - - // Offset (7) 'historicalRoots' - if o7 = ssz.ReadOffset(buf[524464:524468]); o7 > size { - return ssz.ErrOffset - } - - if o7 < 2736629 { - return ssz.ErrInvalidVariableOffset - } - - // Field (8) 'eth1Data' - if b.eth1Data == nil { - b.eth1Data = new(ethpb.Eth1Data) - } - if err = b.eth1Data.UnmarshalSSZ(buf[524468:524540]); err != nil { - return err - } - - // Offset (9) 'eth1DataVotes' - if o9 = ssz.ReadOffset(buf[524540:524544]); o9 > size || o7 > o9 { - return ssz.ErrOffset - } - - // Field (10) 'eth1DepositIndex' - b.eth1DepositIndex = ssz.UnmarshallUint64(buf[524544:524552]) - - // Offset (11) 'validators' - if o11 = ssz.ReadOffset(buf[524552:524556]); o11 > size || o9 > o11 { - return ssz.ErrOffset - } - - // Offset (12) 'balances' - if o12 = ssz.ReadOffset(buf[524556:524560]); o12 > size || o11 > o12 { - return ssz.ErrOffset - } - - // Field (13) 'randaoMixes' - - for ii := 0; ii < 65536; ii++ { - copy(b.randaoMixes[ii][:], buf[524560:2621712][ii*32:(ii+1)*32]) - } - - // Field (14) 'slashings' - b.slashings = ssz.ExtendUint64(b.slashings, 8192) - for ii := 0; ii < 8192; ii++ { - b.slashings[ii] = ssz.UnmarshallUint64(buf[2621712:2687248][ii*8 : (ii+1)*8]) - } - - // Offset (15) 'previousEpochParticipation' - if o15 = ssz.ReadOffset(buf[2687248:2687252]); o15 > size || o12 > o15 { - return ssz.ErrOffset - } - - // Offset (16) 'currentEpochParticipation' - if o16 = ssz.ReadOffset(buf[2687252:2687256]); o16 > size || o15 > o16 { - return ssz.ErrOffset - } - - // Field (17) 'justificationBits' - if cap(b.justificationBits) == 0 { - b.justificationBits = make([]byte, 0, len(buf[2687256:2687257])) - } - b.justificationBits = append(b.justificationBits, buf[2687256:2687257]...) - - // Field (18) 'previousJustifiedCheckpoint' - if b.previousJustifiedCheckpoint == nil { - b.previousJustifiedCheckpoint = new(ethpb.Checkpoint) - } - if err = b.previousJustifiedCheckpoint.UnmarshalSSZ(buf[2687257:2687297]); err != nil { - return err - } - - // Field (19) 'currentJustifiedCheckpoint' - if b.currentJustifiedCheckpoint == nil { - b.currentJustifiedCheckpoint = new(ethpb.Checkpoint) - } - if err = b.currentJustifiedCheckpoint.UnmarshalSSZ(buf[2687297:2687337]); err != nil { - return err - } - - // Field (20) 'finalizedCheckpoint' - if b.finalizedCheckpoint == nil { - b.finalizedCheckpoint = new(ethpb.Checkpoint) - } - if err = b.finalizedCheckpoint.UnmarshalSSZ(buf[2687337:2687377]); err != nil { - return err - } - - // Offset (21) 'inactivityScores' - if o21 = ssz.ReadOffset(buf[2687377:2687381]); o21 > size || o16 > o21 { - return ssz.ErrOffset - } - - // Field (22) 'currentSyncCommittee' - if b.currentSyncCommittee == nil { - b.currentSyncCommittee = new(ethpb.SyncCommittee) - } - if err = b.currentSyncCommittee.UnmarshalSSZ(buf[2687381:2712005]); err != nil { - return err - } - - // Field (23) 'nextSyncCommittee' - if b.nextSyncCommittee == nil { - b.nextSyncCommittee = new(ethpb.SyncCommittee) - } - if err = b.nextSyncCommittee.UnmarshalSSZ(buf[2712005:2736629]); err != nil { - return err - } - - // Field (7) 'historicalRoots' - { - buf = tail[o7:o9] - num, err := ssz.DivideInt2(len(buf), 32, 16777216) - if err != nil { - return err - } - b.historicalRoots = make([][32]byte, num) - for ii := 0; ii < num; ii++ { - copy(b.historicalRoots[ii][:], buf[ii*32:(ii+1)*32]) - } - } - - // Field (9) 'eth1DataVotes' - { - buf = tail[o9:o11] - num, err := ssz.DivideInt2(len(buf), 72, 2048) - if err != nil { - return err - } - b.eth1DataVotes = make([]*ethpb.Eth1Data, num) - for ii := 0; ii < num; ii++ { - if b.eth1DataVotes[ii] == nil { - b.eth1DataVotes[ii] = new(ethpb.Eth1Data) - } - if err = b.eth1DataVotes[ii].UnmarshalSSZ(buf[ii*72 : (ii+1)*72]); err != nil { - return err - } - } - } - - // Field (11) 'validators' - { - buf = tail[o11:o12] - num, err := ssz.DivideInt2(len(buf), 121, 1099511627776) - if err != nil { - return err - } - b.validators = make([]*ethpb.Validator, num) - for ii := 0; ii < num; ii++ { - if b.validators[ii] == nil { - b.validators[ii] = new(ethpb.Validator) - } - if err = b.validators[ii].UnmarshalSSZ(buf[ii*121 : (ii+1)*121]); err != nil { - return err - } - } - } - - // Field (12) 'balances' - { - buf = tail[o12:o15] - num, err := ssz.DivideInt2(len(buf), 8, 1099511627776) - if err != nil { - return err - } - b.balances = ssz.ExtendUint64(b.balances, num) - for ii := 0; ii < num; ii++ { - b.balances[ii] = ssz.UnmarshallUint64(buf[ii*8 : (ii+1)*8]) - } - } - - // Field (15) 'previousEpochParticipation' - { - buf = tail[o15:o16] - if len(buf) > 1099511627776 { - return ssz.ErrBytesLength - } - if cap(b.previousEpochParticipation) == 0 { - b.previousEpochParticipation = make([]byte, 0, len(buf)) - } - b.previousEpochParticipation = append(b.previousEpochParticipation, buf...) - } - - // Field (16) 'currentEpochParticipation' - { - buf = tail[o16:o21] - if len(buf) > 1099511627776 { - return ssz.ErrBytesLength - } - if cap(b.currentEpochParticipation) == 0 { - b.currentEpochParticipation = make([]byte, 0, len(buf)) - } - b.currentEpochParticipation = append(b.currentEpochParticipation, buf...) - } - - // Field (21) 'inactivityScores' - { - buf = tail[o21:] - num, err := ssz.DivideInt2(len(buf), 8, 1099511627776) - if err != nil { - return err - } - b.inactivityScores = ssz.ExtendUint64(b.inactivityScores, num) - for ii := 0; ii < num; ii++ { - b.inactivityScores[ii] = ssz.UnmarshallUint64(buf[ii*8 : (ii+1)*8]) - } - } - return err -} - -// SizeSSZ returns the ssz encoded size in bytes for the BeaconState object -func (b *BeaconState) SizeSSZ() (size int) { - size = 2736629 - - // Field (7) 'historicalRoots' - size += len(b.historicalRoots) * 32 - - // Field (9) 'eth1DataVotes' - size += len(b.eth1DataVotes) * 72 - - // Field (11) 'validators' - size += len(b.validators) * 121 - - // Field (12) 'balances' - size += len(b.balances) * 8 - - // Field (15) 'previousEpochParticipation' - size += len(b.previousEpochParticipation) - - // Field (16) 'currentEpochParticipation' - size += len(b.currentEpochParticipation) - - // Field (21) 'inactivityScores' - size += len(b.inactivityScores) * 8 - - return -} diff --git a/beacon-chain/state/state-native/v2/getters_block.go b/beacon-chain/state/state-native/v2/getters_block.go deleted file mode 100644 index addfc2ea19..0000000000 --- a/beacon-chain/state/state-native/v2/getters_block.go +++ /dev/null @@ -1,84 +0,0 @@ -package v2 - -import ( - "fmt" - - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -// LatestBlockHeader stored within the beacon state. -func (b *BeaconState) LatestBlockHeader() *ethpb.BeaconBlockHeader { - if b.latestBlockHeader == nil { - return nil - } - - b.lock.RLock() - defer b.lock.RUnlock() - - return b.latestBlockHeaderVal() -} - -// latestBlockHeaderVal stored within the beacon state. -// This assumes that a lock is already held on BeaconState. -func (b *BeaconState) latestBlockHeaderVal() *ethpb.BeaconBlockHeader { - if b.latestBlockHeader == nil { - return nil - } - - hdr := ðpb.BeaconBlockHeader{ - Slot: b.latestBlockHeader.Slot, - ProposerIndex: b.latestBlockHeader.ProposerIndex, - } - - parentRoot := make([]byte, len(b.latestBlockHeader.ParentRoot)) - bodyRoot := make([]byte, len(b.latestBlockHeader.BodyRoot)) - stateRoot := make([]byte, len(b.latestBlockHeader.StateRoot)) - - copy(parentRoot, b.latestBlockHeader.ParentRoot) - copy(bodyRoot, b.latestBlockHeader.BodyRoot) - copy(stateRoot, b.latestBlockHeader.StateRoot) - hdr.ParentRoot = parentRoot - hdr.BodyRoot = bodyRoot - hdr.StateRoot = stateRoot - return hdr -} - -// BlockRoots kept track of in the beacon state. -func (b *BeaconState) BlockRoots() [][]byte { - if b.blockRoots == nil { - return nil - } - - b.lock.RLock() - defer b.lock.RUnlock() - - return b.blockRoots.Slice() -} - -// BlockRootAtIndex retrieves a specific block root based on an -// input index value. -func (b *BeaconState) BlockRootAtIndex(idx uint64) ([]byte, error) { - if b.blockRoots == nil { - return nil, nil - } - - b.lock.RLock() - defer b.lock.RUnlock() - - r, err := b.blockRootAtIndex(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{}, fmt.Errorf("index %d out of range", idx) - } - - return b.blockRoots[idx], nil -} diff --git a/beacon-chain/state/state-native/v2/getters_block_test.go b/beacon-chain/state/state-native/v2/getters_block_test.go deleted file mode 100644 index c9aedf24af..0000000000 --- a/beacon-chain/state/state-native/v2/getters_block_test.go +++ /dev/null @@ -1,45 +0,0 @@ -package v2 - -import ( - "testing" - - "github.com/prysmaticlabs/prysm/beacon-chain/state" - testtmpl "github.com/prysmaticlabs/prysm/beacon-chain/state/testing" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -func TestBeaconState_LatestBlockHeader(t *testing.T) { - testtmpl.VerifyBeaconStateLatestBlockHeader( - t, - func() (state.BeaconState, error) { - return InitializeFromProto(ðpb.BeaconStateAltair{}) - }, - func(BH *ethpb.BeaconBlockHeader) (state.BeaconState, error) { - return InitializeFromProto(ðpb.BeaconStateAltair{LatestBlockHeader: BH}) - }, - ) -} - -func TestBeaconState_BlockRoots(t *testing.T) { - testtmpl.VerifyBeaconStateBlockRootsNative( - t, - func() (state.BeaconState, error) { - return InitializeFromProto(ðpb.BeaconStateAltair{}) - }, - func(BR [][]byte) (state.BeaconState, error) { - return InitializeFromProto(ðpb.BeaconStateAltair{BlockRoots: BR}) - }, - ) -} - -func TestBeaconState_BlockRootAtIndex(t *testing.T) { - testtmpl.VerifyBeaconStateBlockRootAtIndexNative( - t, - func() (state.BeaconState, error) { - return InitializeFromProto(ðpb.BeaconStateAltair{}) - }, - func(BR [][]byte) (state.BeaconState, error) { - return InitializeFromProto(ðpb.BeaconStateAltair{BlockRoots: BR}) - }, - ) -} diff --git a/beacon-chain/state/state-native/v2/getters_checkpoint.go b/beacon-chain/state/state-native/v2/getters_checkpoint.go deleted file mode 100644 index bb3919c141..0000000000 --- a/beacon-chain/state/state-native/v2/getters_checkpoint.go +++ /dev/null @@ -1,124 +0,0 @@ -package v2 - -import ( - "bytes" - - "github.com/prysmaticlabs/go-bitfield" - types "github.com/prysmaticlabs/prysm/consensus-types/primitives" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -// JustificationBits marking which epochs have been justified in the beacon chain. -func (b *BeaconState) JustificationBits() bitfield.Bitvector4 { - if b.justificationBits == nil { - return nil - } - - b.lock.RLock() - defer b.lock.RUnlock() - - return b.justificationBitsVal() -} - -// justificationBitsVal marking which epochs have been justified in the beacon chain. -// This assumes that a lock is already held on BeaconState. -func (b *BeaconState) justificationBitsVal() bitfield.Bitvector4 { - if b.justificationBits == nil { - return nil - } - - res := make([]byte, len(b.justificationBits.Bytes())) - copy(res, b.justificationBits.Bytes()) - return res -} - -// PreviousJustifiedCheckpoint denoting an epoch and block root. -func (b *BeaconState) PreviousJustifiedCheckpoint() *ethpb.Checkpoint { - if b.previousJustifiedCheckpoint == nil { - return nil - } - - b.lock.RLock() - defer b.lock.RUnlock() - - return b.previousJustifiedCheckpointVal() -} - -// previousJustifiedCheckpointVal denoting an epoch and block root. -// This assumes that a lock is already held on BeaconState. -func (b *BeaconState) previousJustifiedCheckpointVal() *ethpb.Checkpoint { - return ethpb.CopyCheckpoint(b.previousJustifiedCheckpoint) -} - -// CurrentJustifiedCheckpoint denoting an epoch and block root. -func (b *BeaconState) CurrentJustifiedCheckpoint() *ethpb.Checkpoint { - if b.currentJustifiedCheckpoint == nil { - return nil - } - - b.lock.RLock() - defer b.lock.RUnlock() - - return b.currentJustifiedCheckpointVal() -} - -// currentJustifiedCheckpoint denoting an epoch and block root. -// This assumes that a lock is already held on BeaconState. -func (b *BeaconState) currentJustifiedCheckpointVal() *ethpb.Checkpoint { - return ethpb.CopyCheckpoint(b.currentJustifiedCheckpoint) -} - -// MatchCurrentJustifiedCheckpoint returns true if input justified checkpoint matches -// the current justified checkpoint in state. -func (b *BeaconState) MatchCurrentJustifiedCheckpoint(c *ethpb.Checkpoint) bool { - if b.currentJustifiedCheckpoint == nil { - return false - } - - if c.Epoch != b.currentJustifiedCheckpoint.Epoch { - return false - } - return bytes.Equal(c.Root, b.currentJustifiedCheckpoint.Root) -} - -// MatchPreviousJustifiedCheckpoint returns true if the input justified checkpoint matches -// the previous justified checkpoint in state. -func (b *BeaconState) MatchPreviousJustifiedCheckpoint(c *ethpb.Checkpoint) bool { - if b.previousJustifiedCheckpoint == nil { - return false - } - - if c.Epoch != b.previousJustifiedCheckpoint.Epoch { - return false - } - return bytes.Equal(c.Root, b.previousJustifiedCheckpoint.Root) -} - -// FinalizedCheckpoint denoting an epoch and block root. -func (b *BeaconState) FinalizedCheckpoint() *ethpb.Checkpoint { - if b.finalizedCheckpoint == nil { - return nil - } - - b.lock.RLock() - defer b.lock.RUnlock() - - return b.finalizedCheckpointVal() -} - -// finalizedCheckpointVal denoting an epoch and block root. -// This assumes that a lock is already held on BeaconState. -func (b *BeaconState) finalizedCheckpointVal() *ethpb.Checkpoint { - return ethpb.CopyCheckpoint(b.finalizedCheckpoint) -} - -// FinalizedCheckpointEpoch returns the epoch value of the finalized checkpoint. -func (b *BeaconState) FinalizedCheckpointEpoch() types.Epoch { - if b.finalizedCheckpoint == nil { - return 0 - } - b.lock.RLock() - defer b.lock.RUnlock() - - return b.finalizedCheckpoint.Epoch -} diff --git a/beacon-chain/state/state-native/v2/getters_checkpoint_test.go b/beacon-chain/state/state-native/v2/getters_checkpoint_test.go deleted file mode 100644 index 0090f5dc83..0000000000 --- a/beacon-chain/state/state-native/v2/getters_checkpoint_test.go +++ /dev/null @@ -1,74 +0,0 @@ -package v2 - -import ( - "testing" - - "github.com/prysmaticlabs/go-bitfield" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - testtmpl "github.com/prysmaticlabs/prysm/beacon-chain/state/testing" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -func TestBeaconState_JustificationBitsNil(t *testing.T) { - testtmpl.VerifyBeaconStateJustificationBitsNil( - t, - func() (state.BeaconState, error) { - return InitializeFromProtoUnsafe(ðpb.BeaconStateAltair{}) - }) -} - -func TestBeaconState_JustificationBits(t *testing.T) { - testtmpl.VerifyBeaconStateJustificationBits( - t, - func(bits bitfield.Bitvector4) (state.BeaconState, error) { - return InitializeFromProtoUnsafe(ðpb.BeaconStateAltair{JustificationBits: bits}) - }) -} - -func TestBeaconState_PreviousJustifiedCheckpointNil(t *testing.T) { - testtmpl.VerifyBeaconStatePreviousJustifiedCheckpointNil( - t, - func() (state.BeaconState, error) { - return InitializeFromProtoUnsafe(ðpb.BeaconStateAltair{}) - }) -} - -func TestBeaconState_PreviousJustifiedCheckpoint(t *testing.T) { - testtmpl.VerifyBeaconStatePreviousJustifiedCheckpoint( - t, - func(cp *ethpb.Checkpoint) (state.BeaconState, error) { - return InitializeFromProtoUnsafe(ðpb.BeaconStateAltair{PreviousJustifiedCheckpoint: cp}) - }) -} - -func TestBeaconState_CurrentJustifiedCheckpointNil(t *testing.T) { - testtmpl.VerifyBeaconStateCurrentJustifiedCheckpointNil( - t, - func() (state.BeaconState, error) { - return InitializeFromProtoUnsafe(ðpb.BeaconStateAltair{}) - }) -} - -func TestBeaconState_CurrentJustifiedCheckpoint(t *testing.T) { - testtmpl.VerifyBeaconStateCurrentJustifiedCheckpoint( - t, - func(cp *ethpb.Checkpoint) (state.BeaconState, error) { - return InitializeFromProtoUnsafe(ðpb.BeaconStateAltair{CurrentJustifiedCheckpoint: cp}) - }) -} - -func TestBeaconState_FinalizedCheckpointNil(t *testing.T) { - testtmpl.VerifyBeaconStateFinalizedCheckpointNil( - t, - func() (state.BeaconState, error) { - return InitializeFromProtoUnsafe(ðpb.BeaconStateAltair{}) - }) -} - -func TestBeaconState_FinalizedCheckpoint(t *testing.T) { - testtmpl.VerifyBeaconStateFinalizedCheckpoint( - t, - func(cp *ethpb.Checkpoint) (state.BeaconState, error) { - return InitializeFromProtoUnsafe(ðpb.BeaconStateAltair{FinalizedCheckpoint: cp}) - }) -} diff --git a/beacon-chain/state/state-native/v2/getters_eth1.go b/beacon-chain/state/state-native/v2/getters_eth1.go deleted file mode 100644 index 42610a9ca0..0000000000 --- a/beacon-chain/state/state-native/v2/getters_eth1.go +++ /dev/null @@ -1,64 +0,0 @@ -package v2 - -import ( - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -// Eth1Data corresponding to the proof-of-work chain information stored in the beacon state. -func (b *BeaconState) Eth1Data() *ethpb.Eth1Data { - if b.eth1Data == nil { - return nil - } - - b.lock.RLock() - defer b.lock.RUnlock() - - return b.eth1DataVal() -} - -// eth1DataVal corresponding to the proof-of-work chain information stored in the beacon state. -// This assumes that a lock is already held on BeaconState. -func (b *BeaconState) eth1DataVal() *ethpb.Eth1Data { - if b.eth1Data == nil { - return nil - } - - return ethpb.CopyETH1Data(b.eth1Data) -} - -// Eth1DataVotes corresponds to votes from Ethereum on the canonical proof-of-work chain -// data retrieved from eth1. -func (b *BeaconState) Eth1DataVotes() []*ethpb.Eth1Data { - if b.eth1DataVotes == nil { - return nil - } - - b.lock.RLock() - defer b.lock.RUnlock() - - return b.eth1DataVotesVal() -} - -// eth1DataVotesVal corresponds to votes from Ethereum on the canonical proof-of-work chain -// data retrieved from eth1. -// This assumes that a lock is already held on BeaconState. -func (b *BeaconState) eth1DataVotesVal() []*ethpb.Eth1Data { - if b.eth1DataVotes == nil { - return nil - } - - res := make([]*ethpb.Eth1Data, len(b.eth1DataVotes)) - for i := 0; i < len(res); i++ { - res[i] = ethpb.CopyETH1Data(b.eth1DataVotes[i]) - } - return res -} - -// Eth1DepositIndex corresponds to the index of the deposit made to the -// validator deposit contract at the time of this state's eth1 data. -func (b *BeaconState) Eth1DepositIndex() uint64 { - b.lock.RLock() - defer b.lock.RUnlock() - - return b.eth1DepositIndex -} diff --git a/beacon-chain/state/state-native/v2/getters_participation.go b/beacon-chain/state/state-native/v2/getters_participation.go deleted file mode 100644 index 357ee2c24a..0000000000 --- a/beacon-chain/state/state-native/v2/getters_participation.go +++ /dev/null @@ -1,41 +0,0 @@ -package v2 - -// CurrentEpochParticipation corresponding to participation bits on the beacon chain. -func (b *BeaconState) CurrentEpochParticipation() ([]byte, error) { - if b.currentEpochParticipation == nil { - return nil, nil - } - - b.lock.RLock() - defer b.lock.RUnlock() - - return b.currentEpochParticipationVal(), nil -} - -// PreviousEpochParticipation corresponding to participation bits on the beacon chain. -func (b *BeaconState) PreviousEpochParticipation() ([]byte, error) { - if b.previousEpochParticipation == nil { - return nil, nil - } - - b.lock.RLock() - defer b.lock.RUnlock() - - return b.previousEpochParticipationVal(), nil -} - -// currentEpochParticipationVal corresponding to participation bits on the beacon chain. -// This assumes that a lock is already held on BeaconState. -func (b *BeaconState) currentEpochParticipationVal() []byte { - tmp := make([]byte, len(b.currentEpochParticipation)) - copy(tmp, b.currentEpochParticipation) - return tmp -} - -// previousEpochParticipationVal corresponding to participation bits on the beacon chain. -// This assumes that a lock is already held on BeaconState. -func (b *BeaconState) previousEpochParticipationVal() []byte { - tmp := make([]byte, len(b.previousEpochParticipation)) - copy(tmp, b.previousEpochParticipation) - return tmp -} diff --git a/beacon-chain/state/state-native/v2/getters_randao.go b/beacon-chain/state/state-native/v2/getters_randao.go deleted file mode 100644 index 75676bab07..0000000000 --- a/beacon-chain/state/state-native/v2/getters_randao.go +++ /dev/null @@ -1,67 +0,0 @@ -package v2 - -import ( - "fmt" -) - -// RandaoMixes of block proposers on the beacon chain. -func (b *BeaconState) RandaoMixes() [][]byte { - if b.randaoMixes == nil { - return nil - } - - b.lock.RLock() - defer b.lock.RUnlock() - - return b.randaoMixes.Slice() -} - -// RandaoMixAtIndex retrieves a specific block root based on an -// input index value. -func (b *BeaconState) RandaoMixAtIndex(idx uint64) ([]byte, error) { - if b.randaoMixes == nil { - return nil, nil - } - - b.lock.RLock() - defer b.lock.RUnlock() - - m, err := b.randaoMixAtIndex(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{}, fmt.Errorf("index %d out of range", idx) - } - - return b.randaoMixes[idx], nil -} - -// RandaoMixesLength returns the length of the randao mixes slice. -func (b *BeaconState) RandaoMixesLength() int { - if b.randaoMixes == nil { - return 0 - } - - b.lock.RLock() - defer b.lock.RUnlock() - - return b.randaoMixesLength() -} - -// randaoMixesLength returns the length of the randao mixes slice. -// This assumes that a lock is already held on BeaconState. -func (b *BeaconState) randaoMixesLength() int { - if b.randaoMixes == nil { - return 0 - } - - return len(b.randaoMixes) -} diff --git a/beacon-chain/state/state-native/v2/getters_state.go b/beacon-chain/state/state-native/v2/getters_state.go deleted file mode 100644 index 29323e2c64..0000000000 --- a/beacon-chain/state/state-native/v2/getters_state.go +++ /dev/null @@ -1,145 +0,0 @@ -package v2 - -import ( - "fmt" - - "github.com/pkg/errors" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -// ToProtoUnsafe returns the pointer value of the underlying -// beacon state proto object, bypassing immutability. Use with care. -func (b *BeaconState) ToProtoUnsafe() interface{} { - if b == nil { - return nil - } - - gvrCopy := b.genesisValidatorsRoot - - return ðpb.BeaconStateAltair{ - GenesisTime: b.genesisTime, - GenesisValidatorsRoot: gvrCopy[:], - Slot: b.slot, - Fork: b.fork, - LatestBlockHeader: b.latestBlockHeader, - BlockRoots: b.blockRoots.Slice(), - StateRoots: b.stateRoots.Slice(), - HistoricalRoots: b.historicalRoots.Slice(), - Eth1Data: b.eth1Data, - Eth1DataVotes: b.eth1DataVotes, - Eth1DepositIndex: b.eth1DepositIndex, - Validators: b.validators, - Balances: b.balances, - RandaoMixes: b.randaoMixes.Slice(), - Slashings: b.slashings, - PreviousEpochParticipation: b.previousEpochParticipation, - CurrentEpochParticipation: b.currentEpochParticipation, - JustificationBits: b.justificationBits, - PreviousJustifiedCheckpoint: b.previousJustifiedCheckpoint, - CurrentJustifiedCheckpoint: b.currentJustifiedCheckpoint, - FinalizedCheckpoint: b.finalizedCheckpoint, - InactivityScores: b.inactivityScores, - CurrentSyncCommittee: b.currentSyncCommittee, - NextSyncCommittee: b.nextSyncCommittee, - } -} - -// ToProto the beacon state into a protobuf for usage. -func (b *BeaconState) ToProto() interface{} { - if b == nil { - return nil - } - - b.lock.RLock() - defer b.lock.RUnlock() - - gvrCopy := b.genesisValidatorsRoot - - return ðpb.BeaconStateAltair{ - GenesisTime: b.genesisTime, - GenesisValidatorsRoot: gvrCopy[:], - Slot: b.slot, - Fork: b.forkVal(), - LatestBlockHeader: b.latestBlockHeaderVal(), - BlockRoots: b.blockRoots.Slice(), - StateRoots: b.stateRoots.Slice(), - HistoricalRoots: b.historicalRoots.Slice(), - Eth1Data: b.eth1DataVal(), - Eth1DataVotes: b.eth1DataVotesVal(), - Eth1DepositIndex: b.eth1DepositIndex, - Validators: b.validatorsVal(), - Balances: b.balancesVal(), - RandaoMixes: b.randaoMixes.Slice(), - Slashings: b.slashingsVal(), - PreviousEpochParticipation: b.previousEpochParticipationVal(), - CurrentEpochParticipation: b.currentEpochParticipationVal(), - JustificationBits: b.justificationBitsVal(), - PreviousJustifiedCheckpoint: b.previousJustifiedCheckpointVal(), - CurrentJustifiedCheckpoint: b.currentJustifiedCheckpointVal(), - FinalizedCheckpoint: b.finalizedCheckpointVal(), - InactivityScores: b.inactivityScoresVal(), - CurrentSyncCommittee: b.currentSyncCommitteeVal(), - NextSyncCommittee: b.nextSyncCommitteeVal(), - } -} - -// StateRoots kept track of in the beacon state. -func (b *BeaconState) StateRoots() [][]byte { - if b.stateRoots == nil { - return nil - } - - b.lock.RLock() - defer b.lock.RUnlock() - - return b.stateRoots.Slice() -} - -// StateRootAtIndex retrieves a specific state root based on an -// input index value. -func (b *BeaconState) StateRootAtIndex(idx uint64) ([]byte, error) { - if b.stateRoots == nil { - return nil, nil - } - - b.lock.RLock() - defer b.lock.RUnlock() - - r, err := b.stateRootAtIndex(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. -func (b *BeaconState) stateRootAtIndex(idx uint64) ([32]byte, error) { - if uint64(len(b.stateRoots)) <= idx { - return [32]byte{}, fmt.Errorf("index %d out of range", idx) - } - - return b.stateRoots[idx], nil -} - -// ProtobufBeaconState transforms an input into beacon state hard fork 1 in the form of protobuf. -// Error is returned if the input is not type protobuf beacon state. -func ProtobufBeaconState(s interface{}) (*ethpb.BeaconStateAltair, error) { - pbState, ok := s.(*ethpb.BeaconStateAltair) - if !ok { - return nil, errors.New("input is not type pb.BeaconStateAltair") - } - return pbState, nil -} - -// InnerStateUnsafe returns the pointer value of the underlying -// beacon state proto object, bypassing immutability. Use with care. -func (b *BeaconState) InnerStateUnsafe() interface{} { - return b.ToProtoUnsafe() -} - -// CloneInnerState the beacon state into a protobuf for usage. -func (b *BeaconState) CloneInnerState() interface{} { - return b.ToProto() -} diff --git a/beacon-chain/state/state-native/v2/getters_test.go b/beacon-chain/state/state-native/v2/getters_test.go deleted file mode 100644 index e9c0b70b60..0000000000 --- a/beacon-chain/state/state-native/v2/getters_test.go +++ /dev/null @@ -1,39 +0,0 @@ -package v2 - -import ( - "testing" - - "github.com/prysmaticlabs/prysm/beacon-chain/state" - testtmpl "github.com/prysmaticlabs/prysm/beacon-chain/state/testing" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -func TestBeaconState_SlotDataRace(t *testing.T) { - testtmpl.VerifyBeaconStateSlotDataRace(t, func() (state.BeaconState, error) { - return InitializeFromProto(ðpb.BeaconStateAltair{Slot: 1}) - }) -} - -func TestBeaconState_MatchCurrentJustifiedCheckpt(t *testing.T) { - testtmpl.VerifyBeaconStateMatchCurrentJustifiedCheckptNative( - t, - func(cp *ethpb.Checkpoint) (state.BeaconState, error) { - return InitializeFromProto(ðpb.BeaconStateAltair{CurrentJustifiedCheckpoint: cp}) - }, - ) -} - -func TestBeaconState_MatchPreviousJustifiedCheckpt(t *testing.T) { - testtmpl.VerifyBeaconStateMatchPreviousJustifiedCheckptNative( - t, - func(cp *ethpb.Checkpoint) (state.BeaconState, error) { - return InitializeFromProto(ðpb.BeaconStateAltair{PreviousJustifiedCheckpoint: cp}) - }, - ) -} - -func TestBeaconState_ValidatorByPubkey(t *testing.T) { - testtmpl.VerifyBeaconStateValidatorByPubkey(t, func() (state.BeaconState, error) { - return InitializeFromProto(ðpb.BeaconStateAltair{}) - }) -} diff --git a/beacon-chain/state/state-native/v2/getters_validator.go b/beacon-chain/state/state-native/v2/getters_validator.go deleted file mode 100644 index 6c01971d5c..0000000000 --- a/beacon-chain/state/state-native/v2/getters_validator.go +++ /dev/null @@ -1,281 +0,0 @@ -package v2 - -import ( - "fmt" - - "github.com/pkg/errors" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/v1" - fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" - types "github.com/prysmaticlabs/prysm/consensus-types/primitives" - "github.com/prysmaticlabs/prysm/encoding/bytesutil" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -// ValidatorIndexOutOfRangeError represents an error scenario where a validator does not exist -// at a given index in the validator's array. -type ValidatorIndexOutOfRangeError struct { - message string -} - -var ( - // ErrNilValidatorsInState returns when accessing validators in the state while the state has a - // nil slice for the validators field. - ErrNilValidatorsInState = errors.New("state has nil validator slice") -) - -// NewValidatorIndexOutOfRangeError creates a new error instance. -func NewValidatorIndexOutOfRangeError(index types.ValidatorIndex) ValidatorIndexOutOfRangeError { - return ValidatorIndexOutOfRangeError{ - message: fmt.Sprintf("index %d out of range", index), - } -} - -// Error returns the underlying error message. -func (e *ValidatorIndexOutOfRangeError) Error() string { - return e.message -} - -// Validators participating in consensus on the beacon chain. -func (b *BeaconState) Validators() []*ethpb.Validator { - if b.validators == nil { - return nil - } - - b.lock.RLock() - defer b.lock.RUnlock() - - return b.validatorsVal() -} - -// validatorsVal participating in consensus on the beacon chain. -// This assumes that a lock is already held on BeaconState. -func (b *BeaconState) validatorsVal() []*ethpb.Validator { - if b.validators == nil { - return nil - } - - res := make([]*ethpb.Validator, len(b.validators)) - for i := 0; i < len(res); i++ { - val := b.validators[i] - if val == nil { - continue - } - res[i] = ethpb.CopyValidator(val) - } - 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)) - for i := 0; i < len(res); i++ { - validator := b.validators[i] - if validator == nil { - continue - } - // copy validator reference instead. - res[i] = validator - } - return res -} - -// ValidatorAtIndex is the validator at the provided index. -func (b *BeaconState) ValidatorAtIndex(idx types.ValidatorIndex) (*ethpb.Validator, error) { - if b.validators == nil { - return ðpb.Validator{}, nil - } - if uint64(len(b.validators)) <= uint64(idx) { - e := NewValidatorIndexOutOfRangeError(idx) - return nil, &e - } - - b.lock.RLock() - defer b.lock.RUnlock() - - val := b.validators[idx] - return ethpb.CopyValidator(val), nil -} - -// ValidatorAtIndexReadOnly is the validator at the provided index. This method -// doesn't clone the validator. -func (b *BeaconState) ValidatorAtIndexReadOnly(idx types.ValidatorIndex) (state.ReadOnlyValidator, error) { - if b.validators == nil { - return nil, ErrNilValidatorsInState - } - if uint64(len(b.validators)) <= uint64(idx) { - e := NewValidatorIndexOutOfRangeError(idx) - return nil, &e - } - - b.lock.RLock() - defer b.lock.RUnlock() - - return v1.NewValidator(b.validators[idx]) -} - -// ValidatorIndexByPubkey returns a given validator by its 48-byte public key. -func (b *BeaconState) ValidatorIndexByPubkey(key [fieldparams.BLSPubkeyLength]byte) (types.ValidatorIndex, bool) { - if b == nil || b.valMapHandler == nil || b.valMapHandler.IsNil() { - return 0, false - } - b.lock.RLock() - defer b.lock.RUnlock() - numOfVals := len(b.validators) - - idx, ok := b.valMapHandler.Get(key) - if ok && types.ValidatorIndex(numOfVals) <= idx { - return types.ValidatorIndex(0), false - } - return idx, ok -} - -// PubkeyAtIndex returns the pubkey at the given -// validator index. -func (b *BeaconState) PubkeyAtIndex(idx types.ValidatorIndex) [fieldparams.BLSPubkeyLength]byte { - if uint64(idx) >= uint64(len(b.validators)) { - return [fieldparams.BLSPubkeyLength]byte{} - } - b.lock.RLock() - defer b.lock.RUnlock() - - if b.validators[idx] == nil { - return [fieldparams.BLSPubkeyLength]byte{} - } - return bytesutil.ToBytes48(b.validators[idx].PublicKey) -} - -// NumValidators returns the size of the validator registry. -func (b *BeaconState) NumValidators() int { - b.lock.RLock() - defer b.lock.RUnlock() - - return len(b.validators) -} - -// ReadFromEveryValidator reads values from every validator and applies it to the provided function. -// Warning: This method is potentially unsafe, as it exposes the actual validator registry. -func (b *BeaconState) ReadFromEveryValidator(f func(idx int, val state.ReadOnlyValidator) error) error { - if b.validators == nil { - return errors.New("nil validators in state") - } - b.lock.RLock() - validators := b.validators - b.lock.RUnlock() - - for i, v := range validators { - v, err := v1.NewValidator(v) - if err != nil { - return err - } - if err := f(i, v); err != nil { - return err - } - } - return nil -} - -// Balances of validators participating in consensus on the beacon chain. -func (b *BeaconState) Balances() []uint64 { - if b.balances == nil { - return nil - } - - b.lock.RLock() - defer b.lock.RUnlock() - - return b.balancesVal() -} - -// balancesVal of validators participating in consensus on the beacon chain. -// This assumes that a lock is already held on BeaconState. -func (b *BeaconState) balancesVal() []uint64 { - if b.balances == nil { - return nil - } - - res := make([]uint64, len(b.balances)) - copy(res, b.balances) - return res -} - -// BalanceAtIndex of validator with the provided index. -func (b *BeaconState) BalanceAtIndex(idx types.ValidatorIndex) (uint64, error) { - if b.balances == nil { - return 0, nil - } - - b.lock.RLock() - defer b.lock.RUnlock() - - if uint64(len(b.balances)) <= uint64(idx) { - return 0, fmt.Errorf("index of %d does not exist", idx) - } - return b.balances[idx], nil -} - -// BalancesLength returns the length of the balances slice. -func (b *BeaconState) BalancesLength() int { - if b.balances == nil { - return 0 - } - - b.lock.RLock() - defer b.lock.RUnlock() - - return b.balancesLength() -} - -// Slashings of validators on the beacon chain. -func (b *BeaconState) Slashings() []uint64 { - if b.slashings == nil { - return nil - } - - b.lock.RLock() - defer b.lock.RUnlock() - - return b.slashingsVal() -} - -// slashingsVal of validators on the beacon chain. -// This assumes that a lock is already held on BeaconState. -func (b *BeaconState) slashingsVal() []uint64 { - if b.slashings == nil { - return nil - } - - res := make([]uint64, len(b.slashings)) - copy(res, b.slashings) - return res -} - -// inactivityScoresVal of validators participating in consensus on the beacon chain. -// This assumes that a lock is already held on BeaconState. -func (b *BeaconState) inactivityScoresVal() []uint64 { - if b.inactivityScores == nil { - return nil - } - - res := make([]uint64, len(b.inactivityScores)) - copy(res, b.inactivityScores) - return res -} - -// InactivityScores of validators participating in consensus on the beacon chain. -func (b *BeaconState) InactivityScores() ([]uint64, error) { - if b.inactivityScores == nil { - return nil, nil - } - - b.lock.RLock() - defer b.lock.RUnlock() - - return b.inactivityScoresVal(), nil -} diff --git a/beacon-chain/state/state-native/v2/getters_validator_test.go b/beacon-chain/state/state-native/v2/getters_validator_test.go deleted file mode 100644 index 37c5f8638d..0000000000 --- a/beacon-chain/state/state-native/v2/getters_validator_test.go +++ /dev/null @@ -1,18 +0,0 @@ -package v2_test - -import ( - "testing" - - "github.com/prysmaticlabs/prysm/beacon-chain/state" - testtmpl "github.com/prysmaticlabs/prysm/beacon-chain/state/testing" - v2 "github.com/prysmaticlabs/prysm/beacon-chain/state/v2" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -func TestBeaconState_ValidatorAtIndexReadOnly_HandlesNilSlice(t *testing.T) { - testtmpl.VerifyBeaconStateValidatorAtIndexReadOnlyHandlesNilSlice(t, func() (state.BeaconState, error) { - return v2.InitializeFromProtoUnsafe(ðpb.BeaconStateAltair{ - Validators: nil, - }) - }) -} diff --git a/beacon-chain/state/state-native/v2/proofs.go b/beacon-chain/state/state-native/v2/proofs.go deleted file mode 100644 index 2bf9566a99..0000000000 --- a/beacon-chain/state/state-native/v2/proofs.go +++ /dev/null @@ -1,83 +0,0 @@ -package v2 - -import ( - "context" - "encoding/binary" - - "github.com/prysmaticlabs/prysm/beacon-chain/state/fieldtrie" - "github.com/prysmaticlabs/prysm/encoding/bytesutil" -) - -const ( - finalizedRootIndex = uint64(105) // Precomputed value. -) - -// FinalizedRootGeneralizedIndex for the beacon state. -func FinalizedRootGeneralizedIndex() uint64 { - return finalizedRootIndex -} - -// CurrentSyncCommitteeGeneralizedIndex for the beacon state. -func CurrentSyncCommitteeGeneralizedIndex() uint64 { - return uint64(currentSyncCommittee) -} - -// NextSyncCommitteeGeneralizedIndex for the beacon state. -func NextSyncCommitteeGeneralizedIndex() uint64 { - return uint64(nextSyncCommittee) -} - -// CurrentSyncCommitteeProof from the state's Merkle trie representation. -func (b *BeaconState) CurrentSyncCommitteeProof(ctx context.Context) ([][]byte, error) { - b.lock.Lock() - defer b.lock.Unlock() - // In case the Merkle layers of the trie are not populated, we need - // to perform some initialization. - if err := b.initializeMerkleLayers(ctx); err != nil { - return nil, err - } - // Our beacon state uses a "dirty" fields pattern which requires us to - // recompute branches of the Merkle layers that are marked as dirty. - if err := b.recomputeDirtyFields(ctx); err != nil { - return nil, err - } - return fieldtrie.ProofFromMerkleLayers(b.merkleLayers, currentSyncCommittee), nil -} - -// NextSyncCommitteeProof from the state's Merkle trie representation. -func (b *BeaconState) NextSyncCommitteeProof(ctx context.Context) ([][]byte, error) { - b.lock.Lock() - defer b.lock.Unlock() - if err := b.initializeMerkleLayers(ctx); err != nil { - return nil, err - } - if err := b.recomputeDirtyFields(ctx); err != nil { - return nil, err - } - return fieldtrie.ProofFromMerkleLayers(b.merkleLayers, nextSyncCommittee), nil -} - -// FinalizedRootProof crafts a Merkle proof for the finalized root -// contained within the finalized checkpoint of a beacon state. -func (b *BeaconState) FinalizedRootProof(ctx context.Context) ([][]byte, error) { - b.lock.Lock() - defer b.lock.Unlock() - if err := b.initializeMerkleLayers(ctx); err != nil { - return nil, err - } - if err := b.recomputeDirtyFields(ctx); err != nil { - return nil, err - } - cpt := b.finalizedCheckpoint - // The epoch field of a finalized checkpoint is the neighbor - // index of the finalized root field in its Merkle tree representation - // of the checkpoint. This neighbor is the first element added to the proof. - epochBuf := make([]byte, 8) - binary.LittleEndian.PutUint64(epochBuf, uint64(cpt.Epoch)) - epochRoot := bytesutil.ToBytes32(epochBuf) - proof := make([][]byte, 0) - proof = append(proof, epochRoot[:]) - branch := fieldtrie.ProofFromMerkleLayers(b.merkleLayers, finalizedCheckpoint) - proof = append(proof, branch...) - return proof, nil -} diff --git a/beacon-chain/state/state-native/v2/proofs_test.go b/beacon-chain/state/state-native/v2/proofs_test.go deleted file mode 100644 index 25905bb0c2..0000000000 --- a/beacon-chain/state/state-native/v2/proofs_test.go +++ /dev/null @@ -1,105 +0,0 @@ -package v2_test - -import ( - "context" - "testing" - - v2 "github.com/prysmaticlabs/prysm/beacon-chain/state/v2" - "github.com/prysmaticlabs/prysm/container/trie" - "github.com/prysmaticlabs/prysm/crypto/bls" - "github.com/prysmaticlabs/prysm/testing/require" - "github.com/prysmaticlabs/prysm/testing/util" -) - -func TestBeaconStateMerkleProofs(t *testing.T) { - ctx := context.Background() - st, _ := util.DeterministicGenesisStateAltair(t, 256) - htr, err := st.HashTreeRoot(ctx) - require.NoError(t, err) - t.Run("current sync committee", func(t *testing.T) { - sc, err := st.CurrentSyncCommittee() - require.NoError(t, err) - - // Verify the Merkle proof. - scRoot, err := sc.HashTreeRoot() - require.NoError(t, err) - proof, err := st.CurrentSyncCommitteeProof(ctx) - require.NoError(t, err) - valid := trie.VerifyMerkleProof(htr[:], scRoot[:], v2.CurrentSyncCommitteeGeneralizedIndex(), proof) - require.Equal(t, true, valid) - }) - t.Run("next sync committee", func(t *testing.T) { - nextSC, err := st.NextSyncCommittee() - require.NoError(t, err) - proof, err := st.NextSyncCommitteeProof(ctx) - require.NoError(t, err) - - // Verify the Merkle proof. - nextSCRoot, err := nextSC.HashTreeRoot() - require.NoError(t, err) - valid := trie.VerifyMerkleProof(htr[:], nextSCRoot[:], v2.NextSyncCommitteeGeneralizedIndex(), proof) - require.Equal(t, true, valid) - - // Edit the sync committee. - privKey, err := bls.RandKey() - require.NoError(t, err) - nextSC.AggregatePubkey = privKey.PublicKey().Marshal() - require.NoError(t, st.SetNextSyncCommittee(nextSC)) - - // Verifying the old Merkle proof for the new value should fail. - nextSCRoot, err = nextSC.HashTreeRoot() - require.NoError(t, err) - valid = trie.VerifyMerkleProof(htr[:], nextSCRoot[:], v2.NextSyncCommitteeGeneralizedIndex(), proof) - require.Equal(t, false, valid) - - // Generating a new, valid proof should pass. - proof, err = st.NextSyncCommitteeProof(ctx) - require.NoError(t, err) - htr, err = st.HashTreeRoot(ctx) - require.NoError(t, err) - valid = trie.VerifyMerkleProof(htr[:], nextSCRoot[:], v2.NextSyncCommitteeGeneralizedIndex(), proof) - require.Equal(t, true, valid) - }) - t.Run("finalized root", func(t *testing.T) { - finalizedRoot := st.FinalizedCheckpoint().Root - - // Verify the Merkle proof. - htr, err = st.HashTreeRoot(ctx) - require.NoError(t, err) - proof, err := st.FinalizedRootProof(ctx) - require.NoError(t, err) - gIndex := v2.FinalizedRootGeneralizedIndex() - valid := trie.VerifyMerkleProof(htr[:], finalizedRoot, gIndex, proof) - require.Equal(t, true, valid) - }) - t.Run("recomputes root on dirty fields", func(t *testing.T) { - currentRoot, err := st.HashTreeRoot(ctx) - require.NoError(t, err) - cpt := st.FinalizedCheckpoint() - require.NoError(t, err) - - // Edit the checkpoint. - cpt.Epoch = 100 - require.NoError(t, st.SetFinalizedCheckpoint(cpt)) - - // Produce a proof for the finalized root. - proof, err := st.FinalizedRootProof(ctx) - require.NoError(t, err) - - // We expect the previous step to have triggered - // a recomputation of dirty fields in the beacon state, resulting - // in a new hash tree root as the finalized checkpoint had previously - // changed and should have been marked as a dirty state field. - // The proof validity should be false for the old root, but true for the new. - finalizedRoot := st.FinalizedCheckpoint().Root - gIndex := v2.FinalizedRootGeneralizedIndex() - valid := trie.VerifyMerkleProof(currentRoot[:], finalizedRoot, gIndex, proof) - require.Equal(t, false, valid) - - newRoot, err := st.HashTreeRoot(ctx) - require.NoError(t, err) - - valid = trie.VerifyMerkleProof(newRoot[:], finalizedRoot, gIndex, proof) - require.Equal(t, true, valid) - }) -} diff --git a/beacon-chain/state/state-native/v2/references_test.go b/beacon-chain/state/state-native/v2/references_test.go deleted file mode 100644 index 60cc7917cf..0000000000 --- a/beacon-chain/state/state-native/v2/references_test.go +++ /dev/null @@ -1,223 +0,0 @@ -package v2 - -import ( - "reflect" - "runtime" - "runtime/debug" - "testing" - - "github.com/prysmaticlabs/prysm/beacon-chain/state" - "github.com/prysmaticlabs/prysm/beacon-chain/state/types" - "github.com/prysmaticlabs/prysm/encoding/bytesutil" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/testing/assert" - "github.com/prysmaticlabs/prysm/testing/require" -) - -func TestStateReferenceSharing_Finalizer(t *testing.T) { - // This test showcases the logic on a the RandaoMixes field with the GC finalizer. - - s, err := InitializeFromProtoUnsafe(ðpb.BeaconStateAltair{RandaoMixes: [][]byte{[]byte("foo")}}) - require.NoError(t, err) - assert.Equal(t, uint(1), s.sharedFieldReferences[randaoMixes].Refs(), "Expected a single reference for RANDAO mixes") - - func() { - // Create object in a different scope for GC - b := s.Copy() - assert.Equal(t, uint(2), s.sharedFieldReferences[randaoMixes].Refs(), "Expected 2 references to RANDAO mixes") - _ = b - }() - - runtime.GC() // Should run finalizer on object b - assert.Equal(t, uint(1), s.sharedFieldReferences[randaoMixes].Refs(), "Expected 1 shared reference to RANDAO mixes!") - - copied := s.Copy() - b, ok := copied.(*BeaconState) - require.Equal(t, true, ok) - assert.Equal(t, uint(2), b.sharedFieldReferences[randaoMixes].Refs(), "Expected 2 shared references to RANDAO mixes") - require.NoError(t, b.UpdateRandaoMixesAtIndex(0, []byte("bar"))) - if b.sharedFieldReferences[randaoMixes].Refs() != 1 || s.sharedFieldReferences[randaoMixes].Refs() != 1 { - t.Error("Expected 1 shared reference to RANDAO mix for both a and b") - } -} - -func TestStateReferenceCopy_NoUnexpectedRootsMutation(t *testing.T) { - root1, root2 := bytesutil.ToBytes32([]byte("foo")), bytesutil.ToBytes32([]byte("bar")) - s, err := InitializeFromProtoUnsafe(ðpb.BeaconStateAltair{ - BlockRoots: [][]byte{ - root1[:], - }, - StateRoots: [][]byte{ - root1[:], - }, - }) - require.NoError(t, err) - assertRefCount(t, s, blockRoots, 1) - assertRefCount(t, s, stateRoots, 1) - - // Copy, increases reference count. - copied := s.Copy() - b, ok := copied.(*BeaconState) - require.Equal(t, true, ok) - assertRefCount(t, s, blockRoots, 2) - assertRefCount(t, s, stateRoots, 2) - assertRefCount(t, b, blockRoots, 2) - assertRefCount(t, b, stateRoots, 2) - assert.Equal(t, 8192, len(b.BlockRoots()), "Wrong number of block roots found") - assert.Equal(t, 8192, len(b.StateRoots()), "Wrong number of state roots found") - - // Assert shared state. - blockRootsA := s.BlockRoots() - stateRootsA := s.StateRoots() - blockRootsB := b.BlockRoots() - stateRootsB := b.StateRoots() - if len(blockRootsA) != len(blockRootsB) || len(blockRootsA) < 1 { - t.Errorf("Unexpected number of block roots, want: %v", 1) - } - if len(stateRootsA) != len(stateRootsB) || len(stateRootsA) < 1 { - t.Errorf("Unexpected number of state roots, want: %v", 1) - } - assertValFound(t, blockRootsA, root1[:]) - assertValFound(t, blockRootsB, root1[:]) - assertValFound(t, stateRootsA, root1[:]) - assertValFound(t, stateRootsB, root1[:]) - - // Mutator should only affect calling state: a. - require.NoError(t, s.UpdateBlockRootAtIndex(0, root2)) - require.NoError(t, s.UpdateStateRootAtIndex(0, root2)) - - // Assert no shared state mutation occurred only on state a (copy on write). - assertValNotFound(t, s.BlockRoots(), root1[:]) - assertValNotFound(t, s.StateRoots(), root1[:]) - assertValFound(t, s.BlockRoots(), root2[:]) - assertValFound(t, s.StateRoots(), root2[:]) - assertValFound(t, b.BlockRoots(), root1[:]) - assertValFound(t, b.StateRoots(), root1[:]) - if len(blockRootsA) != len(blockRootsB) || len(blockRootsA) < 1 { - t.Errorf("Unexpected number of block roots, want: %v", 1) - } - if len(stateRootsA) != len(stateRootsB) || len(stateRootsA) < 1 { - t.Errorf("Unexpected number of state roots, want: %v", 1) - } - assert.DeepEqual(t, root2[:], s.BlockRoots()[0], "Expected mutation not found") - assert.DeepEqual(t, root2[:], s.StateRoots()[0], "Expected mutation not found") - assert.DeepEqual(t, root1[:], blockRootsB[0], "Unexpected mutation found") - assert.DeepEqual(t, root1[:], stateRootsB[0], "Unexpected mutation found") - - // Copy on write happened, reference counters are reset. - assertRefCount(t, s, blockRoots, 1) - assertRefCount(t, s, stateRoots, 1) - assertRefCount(t, b, blockRoots, 1) - assertRefCount(t, b, stateRoots, 1) -} - -func TestStateReferenceCopy_NoUnexpectedRandaoMutation(t *testing.T) { - - val1, val2 := bytesutil.PadTo([]byte("foo"), 32), bytesutil.PadTo([]byte("bar"), 32) - s, err := InitializeFromProtoUnsafe(ðpb.BeaconStateAltair{ - RandaoMixes: [][]byte{ - val1, - }, - }) - require.NoError(t, err) - assertRefCount(t, s, randaoMixes, 1) - - // Copy, increases reference count. - copied := s.Copy() - b, ok := copied.(*BeaconState) - require.Equal(t, true, ok) - assertRefCount(t, s, randaoMixes, 2) - assertRefCount(t, b, randaoMixes, 2) - - // Assert shared state. - mixesA := s.RandaoMixes() - mixesB := b.RandaoMixes() - if len(mixesA) != len(mixesB) || len(mixesA) < 1 { - t.Errorf("Unexpected number of mix values, want: %v", 1) - } - assertValFound(t, mixesA, val1) - assertValFound(t, mixesB, val1) - - // Mutator should only affect calling state: a. - require.NoError(t, s.UpdateRandaoMixesAtIndex(0, val2)) - - // Assert no shared state mutation occurred only on state a (copy on write). - if len(mixesA) != len(mixesB) || len(mixesA) < 1 { - t.Errorf("Unexpected number of mix values, want: %v", 1) - } - assertValFound(t, s.RandaoMixes(), val2) - assertValNotFound(t, s.RandaoMixes(), val1) - assertValFound(t, b.RandaoMixes(), val1) - assertValNotFound(t, b.RandaoMixes(), val2) - assertValFound(t, mixesB, val1) - assertValNotFound(t, mixesB, val2) - assert.DeepEqual(t, val2, s.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, s, randaoMixes, 1) - assertRefCount(t, b, randaoMixes, 1) -} - -func TestValidatorReferences_RemainsConsistent(t *testing.T) { - a, err := InitializeFromProtoUnsafe(ðpb.BeaconStateAltair{ - Validators: []*ethpb.Validator{ - {PublicKey: []byte{'A'}}, - {PublicKey: []byte{'B'}}, - {PublicKey: []byte{'C'}}, - {PublicKey: []byte{'D'}}, - {PublicKey: []byte{'E'}}, - }, - }) - require.NoError(t, err) - - // Create a second state. - copied := a.Copy() - b, ok := copied.(*BeaconState) - require.Equal(t, true, ok) - - // Update First Validator. - assert.NoError(t, a.UpdateValidatorAtIndex(0, ðpb.Validator{PublicKey: []byte{'Z'}})) - - assert.DeepNotEqual(t, a.Validators()[0], b.Validators()[0], "validators are equal when they are supposed to be different") - // Modify all validators from copied state. - assert.NoError(t, b.ApplyToEveryValidator(func(idx int, val *ethpb.Validator) (bool, *ethpb.Validator, error) { - return true, ðpb.Validator{PublicKey: []byte{'V'}}, nil - })) - - // Ensure reference is properly accounted for. - assert.NoError(t, a.ReadFromEveryValidator(func(idx int, val state.ReadOnlyValidator) error { - assert.NotEqual(t, bytesutil.ToBytes48([]byte{'V'}), val.PublicKey()) - return nil - })) -} - -// assertRefCount checks whether reference count for a given state -// at a given index is equal to expected amount. -func assertRefCount(t *testing.T, b *BeaconState, idx types.FieldIndex, want uint) { - if cnt := b.sharedFieldReferences[idx].Refs(); cnt != want { - t.Errorf("Unexpected count of references for index %d, want: %v, got: %v", idx, want, cnt) - } -} - -// assertValFound checks whether item with a given value exists in list. -func assertValFound(t *testing.T, vals [][]byte, val []byte) { - for i := range vals { - if reflect.DeepEqual(vals[i], val) { - return - } - } - t.Log(string(debug.Stack())) - t.Fatalf("Expected value not found (%v), want: %v", vals, val) -} - -// assertValNotFound checks whether item with a given value doesn't exist in list. -func assertValNotFound(t *testing.T, vals [][]byte, val []byte) { - for i := range vals { - if reflect.DeepEqual(vals[i], val) { - t.Log(string(debug.Stack())) - t.Errorf("Unexpected value found (%v),: %v", vals, val) - return - } - } -} diff --git a/beacon-chain/state/state-native/v2/setters_block.go b/beacon-chain/state/state-native/v2/setters_block.go deleted file mode 100644 index 36bffacc1b..0000000000 --- a/beacon-chain/state/state-native/v2/setters_block.go +++ /dev/null @@ -1,67 +0,0 @@ -package v2 - -import ( - "fmt" - - customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -// SetLatestBlockHeader in the beacon state. -func (b *BeaconState) SetLatestBlockHeader(val *ethpb.BeaconBlockHeader) error { - b.lock.Lock() - defer b.lock.Unlock() - - b.latestBlockHeader = ethpb.CopyBeaconBlockHeader(val) - b.markFieldAsDirty(latestBlockHeader) - return nil -} - -// SetBlockRoots for the beacon state. Updates the entire -// list to a new value by overwriting the previous one. -func (b *BeaconState) SetBlockRoots(val [][]byte) error { - b.lock.Lock() - defer b.lock.Unlock() - - b.sharedFieldReferences[blockRoots].MinusRef() - b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1) - - var rootsArr [fieldparams.BlockRootsLength][32]byte - for i := 0; i < len(rootsArr); i++ { - copy(rootsArr[i][:], val[i]) - } - roots := customtypes.BlockRoots(rootsArr) - b.blockRoots = &roots - b.markFieldAsDirty(blockRoots) - b.rebuildTrie[blockRoots] = true - return nil -} - -// UpdateBlockRootAtIndex for the beacon state. Updates the block root -// at a specific index to a new value. -func (b *BeaconState) UpdateBlockRootAtIndex(idx uint64, blockRoot [32]byte) error { - if uint64(len(b.blockRoots)) <= idx { - return fmt.Errorf("invalid index provided %d", idx) - } - b.lock.Lock() - defer b.lock.Unlock() - - r := b.blockRoots - if ref := b.sharedFieldReferences[blockRoots]; ref.Refs() > 1 { - // Copy elements in underlying array by reference. - roots := *b.blockRoots - rootsCopy := roots - r = &rootsCopy - ref.MinusRef() - b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1) - } - - r[idx] = blockRoot - b.blockRoots = r - - b.markFieldAsDirty(blockRoots) - b.addDirtyIndices(blockRoots, []uint64{idx}) - return nil -} diff --git a/beacon-chain/state/state-native/v2/setters_eth1.go b/beacon-chain/state/state-native/v2/setters_eth1.go deleted file mode 100644 index 7446ea6838..0000000000 --- a/beacon-chain/state/state-native/v2/setters_eth1.go +++ /dev/null @@ -1,62 +0,0 @@ -package v2 - -import ( - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -// SetEth1Data for the beacon state. -func (b *BeaconState) SetEth1Data(val *ethpb.Eth1Data) error { - b.lock.Lock() - defer b.lock.Unlock() - - b.eth1Data = val - b.markFieldAsDirty(eth1Data) - return nil -} - -// SetEth1DataVotes for the beacon state. Updates the entire -// list to a new value by overwriting the previous one. -func (b *BeaconState) SetEth1DataVotes(val []*ethpb.Eth1Data) error { - b.lock.Lock() - defer b.lock.Unlock() - - b.sharedFieldReferences[eth1DataVotes].MinusRef() - b.sharedFieldReferences[eth1DataVotes] = stateutil.NewRef(1) - - b.eth1DataVotes = val - b.markFieldAsDirty(eth1DataVotes) - b.rebuildTrie[eth1DataVotes] = true - return nil -} - -// SetEth1DepositIndex for the beacon state. -func (b *BeaconState) SetEth1DepositIndex(val uint64) error { - b.lock.Lock() - defer b.lock.Unlock() - - b.eth1DepositIndex = val - b.markFieldAsDirty(eth1DepositIndex) - return nil -} - -// AppendEth1DataVotes for the beacon state. Appends the new value -// to the the end of list. -func (b *BeaconState) AppendEth1DataVotes(val *ethpb.Eth1Data) error { - b.lock.Lock() - defer b.lock.Unlock() - - votes := b.eth1DataVotes - if b.sharedFieldReferences[eth1DataVotes].Refs() > 1 { - // Copy elements in underlying array by reference. - votes = make([]*ethpb.Eth1Data, len(b.eth1DataVotes)) - copy(votes, b.eth1DataVotes) - b.sharedFieldReferences[eth1DataVotes].MinusRef() - b.sharedFieldReferences[eth1DataVotes] = stateutil.NewRef(1) - } - - b.eth1DataVotes = append(votes, val) - b.markFieldAsDirty(eth1DataVotes) - b.addDirtyIndices(eth1DataVotes, []uint64{uint64(len(b.eth1DataVotes) - 1)}) - return nil -} diff --git a/beacon-chain/state/state-native/v2/setters_misc.go b/beacon-chain/state/state-native/v2/setters_misc.go deleted file mode 100644 index b19b98c2dd..0000000000 --- a/beacon-chain/state/state-native/v2/setters_misc.go +++ /dev/null @@ -1,178 +0,0 @@ -package v2 - -import ( - "github.com/pkg/errors" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - stateTypes "github.com/prysmaticlabs/prysm/beacon-chain/state/types" - fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" - types "github.com/prysmaticlabs/prysm/consensus-types/primitives" - "github.com/prysmaticlabs/prysm/crypto/hash" - "github.com/prysmaticlabs/prysm/encoding/bytesutil" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" - "google.golang.org/protobuf/proto" -) - -// For our setters, we have a field reference counter through -// which we can track shared field references. This helps when -// performing state copies, as we simply copy the reference to the -// field. When we do need to do need to modify these fields, we -// perform a full copy of the field. This is true of most of our -// fields except for the following below. -// 1) BlockRoots -// 2) StateRoots -// 3) Eth1DataVotes -// 4) RandaoMixes -// 5) HistoricalRoots -// 6) CurrentParticipationBits -// 7) PreviousParticipationBits -// -// The fields referred to above are instead copied by reference, where -// we simply copy the reference to the underlying object instead of the -// whole object. This is possible due to how we have structured our state -// as we copy the value on read, so as to ensure the underlying object is -// not mutated while it is being accessed during a state read. - -const ( - // This specifies the limit till which we process all dirty indices for a certain field. - // If we have more dirty indices than the threshold, then we rebuild the whole trie. This - // comes due to the fact that O(alogn) > O(n) beyond a certain value of a. - indicesLimit = 8000 -) - -// SetGenesisTime for the beacon state. -func (b *BeaconState) SetGenesisTime(val uint64) error { - b.lock.Lock() - defer b.lock.Unlock() - - b.genesisTime = val - b.markFieldAsDirty(genesisTime) - return nil -} - -// SetGenesisValidatorsRoot for the beacon state. -func (b *BeaconState) SetGenesisValidatorsRoot(val []byte) error { - b.lock.Lock() - defer b.lock.Unlock() - - if len(val) != fieldparams.RootLength { - return errors.New("incorrect validators root length") - } - b.genesisValidatorsRoot = bytesutil.ToBytes32(val) - b.markFieldAsDirty(genesisValidatorsRoot) - return nil -} - -// SetSlot for the beacon state. -func (b *BeaconState) SetSlot(val types.Slot) error { - b.lock.Lock() - defer b.lock.Unlock() - - b.slot = val - b.markFieldAsDirty(slot) - return nil -} - -// SetFork version for the beacon chain. -func (b *BeaconState) SetFork(val *ethpb.Fork) error { - b.lock.Lock() - defer b.lock.Unlock() - - fk, ok := proto.Clone(val).(*ethpb.Fork) - if !ok { - return errors.New("proto.Clone did not return a fork proto") - } - b.fork = fk - b.markFieldAsDirty(fork) - return nil -} - -// SetHistoricalRoots for the beacon state. Updates the entire -// list to a new value by overwriting the previous one. -func (b *BeaconState) SetHistoricalRoots(val [][]byte) error { - b.lock.Lock() - defer b.lock.Unlock() - - b.sharedFieldReferences[historicalRoots].MinusRef() - b.sharedFieldReferences[historicalRoots] = stateutil.NewRef(1) - - roots := make([][32]byte, len(val)) - for i, r := range val { - copy(roots[i][:], r) - } - b.historicalRoots = roots - b.markFieldAsDirty(historicalRoots) - return nil -} - -// AppendHistoricalRoots for the beacon state. Appends the new value -// to the the end of list. -func (b *BeaconState) AppendHistoricalRoots(root [32]byte) error { - b.lock.Lock() - defer b.lock.Unlock() - - roots := b.historicalRoots - if b.sharedFieldReferences[historicalRoots].Refs() > 1 { - roots = make([][32]byte, len(b.historicalRoots)) - copy(roots, b.historicalRoots) - b.sharedFieldReferences[historicalRoots].MinusRef() - b.sharedFieldReferences[historicalRoots] = stateutil.NewRef(1) - } - - b.historicalRoots = append(roots, root) - b.markFieldAsDirty(historicalRoots) - return nil -} - -// Recomputes the branch up the index in the Merkle trie representation -// of the beacon state. This method performs slice reads and the caller MUST -// hold the lock before calling this method. -func (b *BeaconState) recomputeRoot(idx int) { - hashFunc := hash.CustomSHA256Hasher() - layers := b.merkleLayers - // The merkle tree structure looks as follows: - // [[r1, r2, r3, r4], [parent1, parent2], [root]] - // Using information about the index which changed, idx, we recompute - // only its branch up the tree. - currentIndex := idx - root := b.merkleLayers[0][idx] - for i := 0; i < len(layers)-1; i++ { - isLeft := currentIndex%2 == 0 - neighborIdx := currentIndex ^ 1 - - neighbor := make([]byte, 32) - if layers[i] != nil && len(layers[i]) != 0 && neighborIdx < len(layers[i]) { - neighbor = layers[i][neighborIdx] - } - if isLeft { - parentHash := hashFunc(append(root, neighbor...)) - root = parentHash[:] - } else { - parentHash := hashFunc(append(neighbor, root...)) - root = parentHash[:] - } - parentIdx := currentIndex / 2 - // Update the cached layers at the parent index. - layers[i+1][parentIdx] = root - currentIndex = parentIdx - } - b.merkleLayers = layers -} - -func (b *BeaconState) markFieldAsDirty(field stateTypes.FieldIndex) { - b.dirtyFields[field] = true -} - -// addDirtyIndices adds the relevant dirty field indices, so that they -// can be recomputed. -func (b *BeaconState) addDirtyIndices(index stateTypes.FieldIndex, indices []uint64) { - if b.rebuildTrie[index] { - return - } - totalIndicesLen := len(b.dirtyIndices[index]) + len(indices) - if totalIndicesLen > indicesLimit { - b.rebuildTrie[index] = true - b.dirtyIndices[index] = []uint64{} - } else { - b.dirtyIndices[index] = append(b.dirtyIndices[index], indices...) - } -} diff --git a/beacon-chain/state/state-native/v2/setters_participation.go b/beacon-chain/state/state-native/v2/setters_participation.go deleted file mode 100644 index 20e45f61d0..0000000000 --- a/beacon-chain/state/state-native/v2/setters_participation.go +++ /dev/null @@ -1,137 +0,0 @@ -package v2 - -import ( - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" -) - -// SetPreviousParticipationBits for the beacon state. Updates the entire -// list to a new value by overwriting the previous one. -func (b *BeaconState) SetPreviousParticipationBits(val []byte) error { - b.lock.Lock() - defer b.lock.Unlock() - - b.sharedFieldReferences[previousEpochParticipationBits].MinusRef() - b.sharedFieldReferences[previousEpochParticipationBits] = stateutil.NewRef(1) - - b.previousEpochParticipation = val - b.markFieldAsDirty(previousEpochParticipationBits) - b.rebuildTrie[previousEpochParticipationBits] = true - return nil -} - -// SetCurrentParticipationBits for the beacon state. Updates the entire -// list to a new value by overwriting the previous one. -func (b *BeaconState) SetCurrentParticipationBits(val []byte) error { - b.lock.Lock() - defer b.lock.Unlock() - - b.sharedFieldReferences[currentEpochParticipationBits].MinusRef() - b.sharedFieldReferences[currentEpochParticipationBits] = stateutil.NewRef(1) - - b.currentEpochParticipation = val - b.markFieldAsDirty(currentEpochParticipationBits) - b.rebuildTrie[currentEpochParticipationBits] = true - return nil -} - -// AppendCurrentParticipationBits for the beacon state. Appends the new value -// to the the end of list. -func (b *BeaconState) AppendCurrentParticipationBits(val byte) error { - b.lock.Lock() - defer b.lock.Unlock() - - participation := b.currentEpochParticipation - if b.sharedFieldReferences[currentEpochParticipationBits].Refs() > 1 { - // Copy elements in underlying array by reference. - participation = make([]byte, len(b.currentEpochParticipation)) - copy(participation, b.currentEpochParticipation) - b.sharedFieldReferences[currentEpochParticipationBits].MinusRef() - b.sharedFieldReferences[currentEpochParticipationBits] = stateutil.NewRef(1) - } - - b.currentEpochParticipation = append(participation, val) - b.markFieldAsDirty(currentEpochParticipationBits) - b.addDirtyIndices(currentEpochParticipationBits, []uint64{uint64(len(b.currentEpochParticipation) - 1)}) - return nil -} - -// AppendPreviousParticipationBits for the beacon state. Appends the new value -// to the the end of list. -func (b *BeaconState) AppendPreviousParticipationBits(val byte) error { - b.lock.Lock() - defer b.lock.Unlock() - - bits := b.previousEpochParticipation - if b.sharedFieldReferences[previousEpochParticipationBits].Refs() > 1 { - bits = make([]byte, len(b.previousEpochParticipation)) - copy(bits, b.previousEpochParticipation) - b.sharedFieldReferences[previousEpochParticipationBits].MinusRef() - b.sharedFieldReferences[previousEpochParticipationBits] = stateutil.NewRef(1) - } - - b.previousEpochParticipation = append(bits, val) - b.markFieldAsDirty(previousEpochParticipationBits) - b.addDirtyIndices(previousEpochParticipationBits, []uint64{uint64(len(b.previousEpochParticipation) - 1)}) - - return nil -} - -// ModifyPreviousParticipationBits modifies the previous participation bitfield via -// the provided mutator function. -func (b *BeaconState) ModifyPreviousParticipationBits(mutator func(val []byte) ([]byte, error)) error { - b.lock.Lock() - - participation := b.previousEpochParticipation - if b.sharedFieldReferences[previousEpochParticipationBits].Refs() > 1 { - // Copy elements in underlying array by reference. - participation = make([]byte, len(b.previousEpochParticipation)) - copy(participation, b.previousEpochParticipation) - b.sharedFieldReferences[previousEpochParticipationBits].MinusRef() - b.sharedFieldReferences[previousEpochParticipationBits] = stateutil.NewRef(1) - } - // Lock is released so that mutator can - // acquire it. - b.lock.Unlock() - - var err error - participation, err = mutator(participation) - if err != nil { - return err - } - b.lock.Lock() - defer b.lock.Unlock() - b.previousEpochParticipation = participation - b.markFieldAsDirty(previousEpochParticipationBits) - b.rebuildTrie[previousEpochParticipationBits] = true - return nil -} - -// ModifyCurrentParticipationBits modifies the current participation bitfield via -// the provided mutator function. -func (b *BeaconState) ModifyCurrentParticipationBits(mutator func(val []byte) ([]byte, error)) error { - b.lock.Lock() - - participation := b.currentEpochParticipation - if b.sharedFieldReferences[currentEpochParticipationBits].Refs() > 1 { - // Copy elements in underlying array by reference. - participation = make([]byte, len(b.currentEpochParticipation)) - copy(participation, b.currentEpochParticipation) - b.sharedFieldReferences[currentEpochParticipationBits].MinusRef() - b.sharedFieldReferences[currentEpochParticipationBits] = stateutil.NewRef(1) - } - // Lock is released so that mutator can - // acquire it. - b.lock.Unlock() - - var err error - participation, err = mutator(participation) - if err != nil { - return err - } - b.lock.Lock() - defer b.lock.Unlock() - b.currentEpochParticipation = participation - b.markFieldAsDirty(currentEpochParticipationBits) - b.rebuildTrie[currentEpochParticipationBits] = true - return nil -} diff --git a/beacon-chain/state/state-native/v2/setters_randao.go b/beacon-chain/state/state-native/v2/setters_randao.go deleted file mode 100644 index a2d27c59e4..0000000000 --- a/beacon-chain/state/state-native/v2/setters_randao.go +++ /dev/null @@ -1,56 +0,0 @@ -package v2 - -import ( - "github.com/pkg/errors" - customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" - "github.com/prysmaticlabs/prysm/encoding/bytesutil" -) - -// SetRandaoMixes for the beacon state. Updates the entire -// randao mixes to a new value by overwriting the previous one. -func (b *BeaconState) SetRandaoMixes(val [][]byte) error { - b.lock.Lock() - defer b.lock.Unlock() - - b.sharedFieldReferences[randaoMixes].MinusRef() - b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1) - - var mixesArr [fieldparams.RandaoMixesLength][32]byte - for i := 0; i < len(mixesArr); i++ { - copy(mixesArr[i][:], val[i]) - } - mixes := customtypes.RandaoMixes(mixesArr) - b.randaoMixes = &mixes - b.markFieldAsDirty(randaoMixes) - b.rebuildTrie[randaoMixes] = true - return nil -} - -// UpdateRandaoMixesAtIndex for the beacon state. Updates the randao mixes -// at a specific index to a new value. -func (b *BeaconState) UpdateRandaoMixesAtIndex(idx uint64, val []byte) error { - if uint64(len(b.randaoMixes)) <= idx { - return errors.Errorf("invalid index provided %d", idx) - } - b.lock.Lock() - defer b.lock.Unlock() - - mixes := b.randaoMixes - if refs := b.sharedFieldReferences[randaoMixes].Refs(); refs > 1 { - // Copy elements in underlying array by reference. - m := *b.randaoMixes - mCopy := m - mixes = &mCopy - b.sharedFieldReferences[randaoMixes].MinusRef() - b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1) - } - - mixes[idx] = bytesutil.ToBytes32(val) - b.randaoMixes = mixes - b.markFieldAsDirty(randaoMixes) - b.addDirtyIndices(randaoMixes, []uint64{idx}) - - return nil -} diff --git a/beacon-chain/state/state-native/v2/setters_state.go b/beacon-chain/state/state-native/v2/setters_state.go deleted file mode 100644 index d2ce664f65..0000000000 --- a/beacon-chain/state/state-native/v2/setters_state.go +++ /dev/null @@ -1,60 +0,0 @@ -package v2 - -import ( - "github.com/pkg/errors" - customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" -) - -// SetStateRoots for the beacon state. Updates the state roots -// to a new value by overwriting the previous value. -func (b *BeaconState) SetStateRoots(val [][]byte) error { - b.lock.Lock() - defer b.lock.Unlock() - - b.sharedFieldReferences[stateRoots].MinusRef() - b.sharedFieldReferences[stateRoots] = stateutil.NewRef(1) - - var rootsArr [fieldparams.StateRootsLength][32]byte - for i := 0; i < len(rootsArr); i++ { - copy(rootsArr[i][:], val[i]) - } - roots := customtypes.StateRoots(rootsArr) - b.stateRoots = &roots - b.markFieldAsDirty(stateRoots) - b.rebuildTrie[stateRoots] = true - return nil -} - -// 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 { - b.lock.RLock() - if uint64(len(b.stateRoots)) <= idx { - b.lock.RUnlock() - return errors.Errorf("invalid index provided %d", idx) - } - b.lock.RUnlock() - - b.lock.Lock() - defer b.lock.Unlock() - - // Check if we hold the only reference to the shared state roots slice. - r := b.stateRoots - if ref := b.sharedFieldReferences[stateRoots]; ref.Refs() > 1 { - // Copy elements in underlying array by reference. - roots := *b.stateRoots - rootsCopy := roots - r = &rootsCopy - ref.MinusRef() - b.sharedFieldReferences[stateRoots] = stateutil.NewRef(1) - } - - r[idx] = stateRoot - b.stateRoots = r - - b.markFieldAsDirty(stateRoots) - b.addDirtyIndices(stateRoots, []uint64{idx}) - return nil -} diff --git a/beacon-chain/state/state-native/v2/setters_sync_committee.go b/beacon-chain/state/state-native/v2/setters_sync_committee.go deleted file mode 100644 index 47ecc49fd1..0000000000 --- a/beacon-chain/state/state-native/v2/setters_sync_committee.go +++ /dev/null @@ -1,25 +0,0 @@ -package v2 - -import ( - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -// SetCurrentSyncCommittee for the beacon state. -func (b *BeaconState) SetCurrentSyncCommittee(val *ethpb.SyncCommittee) error { - b.lock.Lock() - defer b.lock.Unlock() - - b.currentSyncCommittee = val - b.markFieldAsDirty(currentSyncCommittee) - return nil -} - -// SetNextSyncCommittee for the beacon state. -func (b *BeaconState) SetNextSyncCommittee(val *ethpb.SyncCommittee) error { - b.lock.Lock() - defer b.lock.Unlock() - - b.nextSyncCommittee = val - b.markFieldAsDirty(nextSyncCommittee) - return nil -} diff --git a/beacon-chain/state/state-native/v2/setters_test.go b/beacon-chain/state/state-native/v2/setters_test.go deleted file mode 100644 index 382179576b..0000000000 --- a/beacon-chain/state/state-native/v2/setters_test.go +++ /dev/null @@ -1,178 +0,0 @@ -package v2 - -import ( - "context" - "strconv" - "testing" - - "github.com/prysmaticlabs/go-bitfield" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - testtmpl "github.com/prysmaticlabs/prysm/beacon-chain/state/testing" - fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" - "github.com/prysmaticlabs/prysm/config/params" - types "github.com/prysmaticlabs/prysm/consensus-types/primitives" - "github.com/prysmaticlabs/prysm/encoding/bytesutil" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/testing/assert" - "github.com/prysmaticlabs/prysm/testing/require" -) - -func TestBeaconState_AppendBalanceWithTrie(t *testing.T) { - count := uint64(100) - vals := make([]*ethpb.Validator, 0, count) - bals := make([]uint64, 0, count) - for i := uint64(1); i < count; i++ { - someRoot := [fieldparams.RootLength]byte{} - someKey := [fieldparams.BLSPubkeyLength]byte{} - copy(someRoot[:], strconv.Itoa(int(i))) - copy(someKey[:], strconv.Itoa(int(i))) - vals = append(vals, ðpb.Validator{ - PublicKey: someKey[:], - WithdrawalCredentials: someRoot[:], - EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, - Slashed: false, - ActivationEligibilityEpoch: 1, - ActivationEpoch: 1, - ExitEpoch: 1, - WithdrawableEpoch: 1, - }) - bals = append(bals, params.BeaconConfig().MaxEffectiveBalance) - } - zeroHash := params.BeaconConfig().ZeroHash - mockblockRoots := make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot) - for i := 0; i < len(mockblockRoots); i++ { - mockblockRoots[i] = zeroHash[:] - } - - mockstateRoots := make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot) - for i := 0; i < len(mockstateRoots); i++ { - mockstateRoots[i] = zeroHash[:] - } - mockrandaoMixes := make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector) - for i := 0; i < len(mockrandaoMixes); i++ { - mockrandaoMixes[i] = zeroHash[:] - } - var pubKeys [][]byte - for i := uint64(0); i < params.BeaconConfig().SyncCommitteeSize; i++ { - pubKeys = append(pubKeys, bytesutil.PadTo([]byte{}, params.BeaconConfig().BLSPubkeyLength)) - } - st, err := InitializeFromProto(ðpb.BeaconStateAltair{ - Slot: 1, - GenesisValidatorsRoot: make([]byte, fieldparams.RootLength), - Fork: ðpb.Fork{ - PreviousVersion: make([]byte, 4), - CurrentVersion: make([]byte, 4), - Epoch: 0, - }, - LatestBlockHeader: ðpb.BeaconBlockHeader{ - ParentRoot: make([]byte, fieldparams.RootLength), - StateRoot: make([]byte, fieldparams.RootLength), - BodyRoot: make([]byte, fieldparams.RootLength), - }, - CurrentEpochParticipation: []byte{}, - PreviousEpochParticipation: []byte{}, - Validators: vals, - Balances: bals, - Eth1Data: ðpb.Eth1Data{ - DepositRoot: make([]byte, fieldparams.RootLength), - BlockHash: make([]byte, fieldparams.RootLength), - }, - BlockRoots: mockblockRoots, - StateRoots: mockstateRoots, - RandaoMixes: mockrandaoMixes, - JustificationBits: bitfield.NewBitvector4(), - PreviousJustifiedCheckpoint: ðpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)}, - CurrentJustifiedCheckpoint: ðpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)}, - FinalizedCheckpoint: ðpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)}, - Slashings: make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector), - CurrentSyncCommittee: ðpb.SyncCommittee{ - Pubkeys: pubKeys, - AggregatePubkey: make([]byte, fieldparams.BLSPubkeyLength), - }, - NextSyncCommittee: ðpb.SyncCommittee{ - Pubkeys: pubKeys, - AggregatePubkey: make([]byte, fieldparams.BLSPubkeyLength), - }, - }) - assert.NoError(t, err) - _, err = st.HashTreeRoot(context.Background()) - assert.NoError(t, err) - - for i := 0; i < 100; i++ { - if i%2 == 0 { - assert.NoError(t, st.UpdateBalancesAtIndex(types.ValidatorIndex(i), 1000)) - } - if i%3 == 0 { - assert.NoError(t, st.AppendBalance(1000)) - } - } - _, err = st.HashTreeRoot(context.Background()) - assert.NoError(t, err) - s, ok := st.(*BeaconState) - require.Equal(t, true, ok) - newRt := bytesutil.ToBytes32(s.merkleLayers[0][balances]) - wantedRt, err := stateutil.Uint64ListRootWithRegistryLimit(st.Balances()) - assert.NoError(t, err) - assert.Equal(t, wantedRt, newRt, "state roots are unequal") -} - -func TestBeaconState_ModifyPreviousParticipationBits(t *testing.T) { - testState := createState(200) - testtmpl.VerifyBeaconStateModifyPreviousParticipationField( - t, - func() (state.BeaconState, error) { - return InitializeFromProto(testState) - }, - ) - testtmpl.VerifyBeaconStateModifyPreviousParticipationField_NestedAction( - t, - func() (state.BeaconState, error) { - return InitializeFromProto(testState) - }, - ) -} - -func TestBeaconState_ModifyCurrentParticipationBits(t *testing.T) { - testState := createState(200) - testtmpl.VerifyBeaconStateModifyCurrentParticipationField( - t, - func() (state.BeaconState, error) { - return InitializeFromProto(testState) - }, - ) - testtmpl.VerifyBeaconStateModifyCurrentParticipationField_NestedAction( - t, - func() (state.BeaconState, error) { - return InitializeFromProto(testState) - }, - ) -} - -func createState(count uint64) *ethpb.BeaconStateAltair { - vals := make([]*ethpb.Validator, 0, count) - bals := make([]uint64, 0, count) - for i := uint64(0); i < count; i++ { - someRoot := [32]byte{} - someKey := [fieldparams.BLSPubkeyLength]byte{} - copy(someRoot[:], strconv.Itoa(int(i))) - copy(someKey[:], strconv.Itoa(int(i))) - vals = append(vals, ðpb.Validator{ - PublicKey: someKey[:], - WithdrawalCredentials: someRoot[:], - EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, - Slashed: false, - ActivationEligibilityEpoch: 1, - ActivationEpoch: 1, - ExitEpoch: 1, - WithdrawableEpoch: 1, - }) - bals = append(bals, params.BeaconConfig().MaxEffectiveBalance) - } - return ðpb.BeaconStateAltair{ - CurrentEpochParticipation: make([]byte, count), - PreviousEpochParticipation: make([]byte, count), - Validators: vals, - Balances: bals, - } -} diff --git a/beacon-chain/state/state-native/v2/setters_validator.go b/beacon-chain/state/state-native/v2/setters_validator.go deleted file mode 100644 index ce25d43eba..0000000000 --- a/beacon-chain/state/state-native/v2/setters_validator.go +++ /dev/null @@ -1,232 +0,0 @@ -package v2 - -import ( - "github.com/pkg/errors" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - types "github.com/prysmaticlabs/prysm/consensus-types/primitives" - "github.com/prysmaticlabs/prysm/encoding/bytesutil" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -// SetValidators for the beacon state. Updates the entire -// to a new value by overwriting the previous one. -func (b *BeaconState) SetValidators(val []*ethpb.Validator) error { - b.lock.Lock() - defer b.lock.Unlock() - - b.validators = val - b.sharedFieldReferences[validators].MinusRef() - b.sharedFieldReferences[validators] = stateutil.NewRef(1) - b.markFieldAsDirty(validators) - b.rebuildTrie[validators] = true - b.valMapHandler = stateutil.NewValMapHandler(b.validators) - return nil -} - -// ApplyToEveryValidator applies the provided callback function to each validator in the -// validator registry. -func (b *BeaconState) ApplyToEveryValidator(f func(idx int, val *ethpb.Validator) (bool, *ethpb.Validator, error)) error { - b.lock.Lock() - v := b.validators - if ref := b.sharedFieldReferences[validators]; ref.Refs() > 1 { - v = b.validatorsReferences() - ref.MinusRef() - b.sharedFieldReferences[validators] = stateutil.NewRef(1) - } - b.lock.Unlock() - var changedVals []uint64 - for i, val := range v { - changed, newVal, err := f(i, val) - if err != nil { - return err - } - if changed { - changedVals = append(changedVals, uint64(i)) - v[i] = newVal - } - } - - b.lock.Lock() - defer b.lock.Unlock() - - b.validators = v - b.markFieldAsDirty(validators) - b.addDirtyIndices(validators, changedVals) - - return nil -} - -// UpdateValidatorAtIndex for the beacon state. Updates the validator -// at a specific index to a new value. -func (b *BeaconState) UpdateValidatorAtIndex(idx types.ValidatorIndex, val *ethpb.Validator) error { - if uint64(len(b.validators)) <= uint64(idx) { - return errors.Errorf("invalid index provided %d", idx) - } - b.lock.Lock() - defer b.lock.Unlock() - - v := b.validators - if ref := b.sharedFieldReferences[validators]; ref.Refs() > 1 { - v = b.validatorsReferences() - ref.MinusRef() - b.sharedFieldReferences[validators] = stateutil.NewRef(1) - } - - v[idx] = val - b.validators = v - b.markFieldAsDirty(validators) - b.addDirtyIndices(validators, []uint64{uint64(idx)}) - - return nil -} - -// SetBalances for the beacon state. Updates the entire -// list to a new value by overwriting the previous one. -func (b *BeaconState) SetBalances(val []uint64) error { - b.lock.Lock() - defer b.lock.Unlock() - - b.sharedFieldReferences[balances].MinusRef() - b.sharedFieldReferences[balances] = stateutil.NewRef(1) - - b.balances = val - b.rebuildTrie[balances] = true - b.markFieldAsDirty(balances) - return nil -} - -// UpdateBalancesAtIndex for the beacon state. This method updates the balance -// at a specific index to a new value. -func (b *BeaconState) UpdateBalancesAtIndex(idx types.ValidatorIndex, val uint64) error { - if uint64(len(b.balances)) <= uint64(idx) { - return errors.Errorf("invalid index provided %d", idx) - } - b.lock.Lock() - defer b.lock.Unlock() - - bals := b.balances - if b.sharedFieldReferences[balances].Refs() > 1 { - bals = b.balancesVal() - b.sharedFieldReferences[balances].MinusRef() - b.sharedFieldReferences[balances] = stateutil.NewRef(1) - } - - bals[idx] = val - b.balances = bals - b.markFieldAsDirty(balances) - b.addDirtyIndices(balances, []uint64{uint64(idx)}) - return nil -} - -// SetSlashings for the beacon state. Updates the entire -// list to a new value by overwriting the previous one. -func (b *BeaconState) SetSlashings(val []uint64) error { - b.lock.Lock() - defer b.lock.Unlock() - - b.sharedFieldReferences[slashings].MinusRef() - b.sharedFieldReferences[slashings] = stateutil.NewRef(1) - - b.slashings = val - b.markFieldAsDirty(slashings) - return nil -} - -// UpdateSlashingsAtIndex for the beacon state. Updates the slashings -// at a specific index to a new value. -func (b *BeaconState) UpdateSlashingsAtIndex(idx, val uint64) error { - if uint64(len(b.slashings)) <= idx { - return errors.Errorf("invalid index provided %d", idx) - } - b.lock.Lock() - defer b.lock.Unlock() - - s := b.slashings - if b.sharedFieldReferences[slashings].Refs() > 1 { - s = b.slashingsVal() - b.sharedFieldReferences[slashings].MinusRef() - b.sharedFieldReferences[slashings] = stateutil.NewRef(1) - } - - s[idx] = val - - b.slashings = s - - b.markFieldAsDirty(slashings) - return nil -} - -// AppendValidator for the beacon state. Appends the new value -// to the the end of list. -func (b *BeaconState) AppendValidator(val *ethpb.Validator) error { - b.lock.Lock() - defer b.lock.Unlock() - - vals := b.validators - if b.sharedFieldReferences[validators].Refs() > 1 { - vals = b.validatorsReferences() - b.sharedFieldReferences[validators].MinusRef() - b.sharedFieldReferences[validators] = stateutil.NewRef(1) - } - - // append validator to slice - b.validators = append(vals, val) - valIdx := types.ValidatorIndex(len(b.validators) - 1) - - b.valMapHandler.Set(bytesutil.ToBytes48(val.PublicKey), valIdx) - - b.markFieldAsDirty(validators) - b.addDirtyIndices(validators, []uint64{uint64(valIdx)}) - return nil -} - -// AppendBalance for the beacon state. Appends the new value -// to the the end of list. -func (b *BeaconState) AppendBalance(bal uint64) error { - b.lock.Lock() - defer b.lock.Unlock() - - bals := b.balances - if b.sharedFieldReferences[balances].Refs() > 1 { - bals = b.balancesVal() - b.sharedFieldReferences[balances].MinusRef() - b.sharedFieldReferences[balances] = stateutil.NewRef(1) - } - - b.balances = append(bals, bal) - balIdx := len(b.balances) - 1 - b.markFieldAsDirty(balances) - b.addDirtyIndices(balances, []uint64{uint64(balIdx)}) - return nil -} - -// AppendInactivityScore for the beacon state. -func (b *BeaconState) AppendInactivityScore(s uint64) error { - b.lock.Lock() - defer b.lock.Unlock() - - scores := b.inactivityScores - if b.sharedFieldReferences[inactivityScores].Refs() > 1 { - scores = b.inactivityScoresVal() - b.sharedFieldReferences[inactivityScores].MinusRef() - b.sharedFieldReferences[inactivityScores] = stateutil.NewRef(1) - } - - b.inactivityScores = append(scores, s) - b.markFieldAsDirty(inactivityScores) - return nil -} - -// SetInactivityScores for the beacon state. Updates the entire -// list to a new value by overwriting the previous one. -func (b *BeaconState) SetInactivityScores(val []uint64) error { - b.lock.Lock() - defer b.lock.Unlock() - - b.sharedFieldReferences[inactivityScores].MinusRef() - b.sharedFieldReferences[inactivityScores] = stateutil.NewRef(1) - - b.inactivityScores = val - b.markFieldAsDirty(inactivityScores) - return nil -} diff --git a/beacon-chain/state/state-native/v2/state_trie.go b/beacon-chain/state/state-native/v2/state_trie.go deleted file mode 100644 index 52c4f33ddd..0000000000 --- a/beacon-chain/state/state-native/v2/state_trie.go +++ /dev/null @@ -1,462 +0,0 @@ -package v2 - -import ( - "context" - "runtime" - "sort" - - "github.com/pkg/errors" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - "github.com/prysmaticlabs/prysm/beacon-chain/state/fieldtrie" - customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - "github.com/prysmaticlabs/prysm/beacon-chain/state/types" - fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" - "github.com/prysmaticlabs/prysm/config/params" - "github.com/prysmaticlabs/prysm/container/slice" - "github.com/prysmaticlabs/prysm/crypto/hash" - "github.com/prysmaticlabs/prysm/encoding/bytesutil" - "github.com/prysmaticlabs/prysm/encoding/ssz" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" - "go.opencensus.io/trace" - "google.golang.org/protobuf/proto" -) - -// InitializeFromProto the beacon state from a protobuf representation. -func InitializeFromProto(st *ethpb.BeaconStateAltair) (state.BeaconStateAltair, error) { - return InitializeFromProtoUnsafe(proto.Clone(st).(*ethpb.BeaconStateAltair)) -} - -// InitializeFromProtoUnsafe directly uses the beacon state protobuf fields -// and sets them as fields of the BeaconState type. -func InitializeFromProtoUnsafe(st *ethpb.BeaconStateAltair) (*BeaconState, error) { - if st == nil { - return nil, errors.New("received nil state") - } - - var bRoots customtypes.BlockRoots - for i, r := range st.BlockRoots { - bRoots[i] = bytesutil.ToBytes32(r) - } - var sRoots customtypes.StateRoots - for i, r := range st.StateRoots { - sRoots[i] = bytesutil.ToBytes32(r) - } - hRoots := customtypes.HistoricalRoots(make([][32]byte, len(st.HistoricalRoots))) - for i, r := range st.HistoricalRoots { - hRoots[i] = bytesutil.ToBytes32(r) - } - var mixes customtypes.RandaoMixes - for i, m := range st.RandaoMixes { - mixes[i] = bytesutil.ToBytes32(m) - } - - fieldCount := params.BeaconConfig().BeaconStateAltairFieldCount - b := &BeaconState{ - genesisTime: st.GenesisTime, - genesisValidatorsRoot: bytesutil.ToBytes32(st.GenesisValidatorsRoot), - slot: st.Slot, - fork: st.Fork, - latestBlockHeader: st.LatestBlockHeader, - blockRoots: &bRoots, - stateRoots: &sRoots, - historicalRoots: hRoots, - eth1Data: st.Eth1Data, - eth1DataVotes: st.Eth1DataVotes, - eth1DepositIndex: st.Eth1DepositIndex, - validators: st.Validators, - balances: st.Balances, - randaoMixes: &mixes, - slashings: st.Slashings, - previousEpochParticipation: st.PreviousEpochParticipation, - currentEpochParticipation: st.CurrentEpochParticipation, - justificationBits: st.JustificationBits, - previousJustifiedCheckpoint: st.PreviousJustifiedCheckpoint, - currentJustifiedCheckpoint: st.CurrentJustifiedCheckpoint, - finalizedCheckpoint: st.FinalizedCheckpoint, - inactivityScores: st.InactivityScores, - currentSyncCommittee: st.CurrentSyncCommittee, - nextSyncCommittee: st.NextSyncCommittee, - - dirtyFields: make(map[types.FieldIndex]bool, fieldCount), - dirtyIndices: make(map[types.FieldIndex][]uint64, fieldCount), - stateFieldLeaves: make(map[types.FieldIndex]*fieldtrie.FieldTrie, fieldCount), - sharedFieldReferences: make(map[types.FieldIndex]*stateutil.Reference, 11), - rebuildTrie: make(map[types.FieldIndex]bool, fieldCount), - valMapHandler: stateutil.NewValMapHandler(st.Validators), - } - - var err error - for i := 0; i < fieldCount; i++ { - b.dirtyFields[types.FieldIndex(i)] = true - b.rebuildTrie[types.FieldIndex(i)] = true - b.dirtyIndices[types.FieldIndex(i)] = []uint64{} - b.stateFieldLeaves[types.FieldIndex(i)], err = fieldtrie.NewFieldTrie(types.FieldIndex(i), types.BasicArray, nil, 0) - if err != nil { - return nil, err - } - } - - // Initialize field reference tracking for shared data. - b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1) - b.sharedFieldReferences[stateRoots] = stateutil.NewRef(1) - b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1) - b.sharedFieldReferences[previousEpochParticipationBits] = stateutil.NewRef(1) // New in Altair. - b.sharedFieldReferences[currentEpochParticipationBits] = stateutil.NewRef(1) // New in Altair. - b.sharedFieldReferences[slashings] = stateutil.NewRef(1) - b.sharedFieldReferences[eth1DataVotes] = stateutil.NewRef(1) - b.sharedFieldReferences[validators] = stateutil.NewRef(1) - b.sharedFieldReferences[balances] = stateutil.NewRef(1) - b.sharedFieldReferences[inactivityScores] = stateutil.NewRef(1) // New in Altair. - b.sharedFieldReferences[historicalRoots] = stateutil.NewRef(1) - - state.StateCount.Inc() - return b, nil -} - -// Copy returns a deep copy of the beacon state. -func (b *BeaconState) Copy() state.BeaconState { - b.lock.RLock() - defer b.lock.RUnlock() - fieldCount := params.BeaconConfig().BeaconStateAltairFieldCount - - dst := &BeaconState{ - // Primitive types, safe to copy. - genesisTime: b.genesisTime, - slot: b.slot, - eth1DepositIndex: b.eth1DepositIndex, - - // Large arrays, infrequently changed, constant size. - blockRoots: b.blockRoots, - stateRoots: b.stateRoots, - randaoMixes: b.randaoMixes, - slashings: b.slashings, - eth1DataVotes: b.eth1DataVotes, - - // Large arrays, increases over time. - historicalRoots: b.historicalRoots, - balances: b.balances, - previousEpochParticipation: b.previousEpochParticipation, - currentEpochParticipation: b.currentEpochParticipation, - inactivityScores: b.inactivityScores, - validators: b.validators, - - // Everything else, too small to be concerned about, constant size. - genesisValidatorsRoot: b.genesisValidatorsRoot, - justificationBits: b.justificationBitsVal(), - fork: b.forkVal(), - latestBlockHeader: b.latestBlockHeaderVal(), - eth1Data: b.eth1DataVal(), - previousJustifiedCheckpoint: b.previousJustifiedCheckpointVal(), - currentJustifiedCheckpoint: b.currentJustifiedCheckpointVal(), - finalizedCheckpoint: b.finalizedCheckpointVal(), - currentSyncCommittee: b.currentSyncCommitteeVal(), - nextSyncCommittee: b.nextSyncCommitteeVal(), - - dirtyFields: make(map[types.FieldIndex]bool, fieldCount), - dirtyIndices: make(map[types.FieldIndex][]uint64, fieldCount), - rebuildTrie: make(map[types.FieldIndex]bool, fieldCount), - sharedFieldReferences: make(map[types.FieldIndex]*stateutil.Reference, 11), - stateFieldLeaves: make(map[types.FieldIndex]*fieldtrie.FieldTrie, fieldCount), - - // Share the reference to validator index map. - valMapHandler: b.valMapHandler, - } - - for field, ref := range b.sharedFieldReferences { - ref.AddRef() - dst.sharedFieldReferences[field] = ref - } - - // Increment ref for validator map - b.valMapHandler.AddRef() - - for i := range b.dirtyFields { - dst.dirtyFields[i] = true - } - - for i := range b.dirtyIndices { - indices := make([]uint64, len(b.dirtyIndices[i])) - copy(indices, b.dirtyIndices[i]) - dst.dirtyIndices[i] = indices - } - - for i := range b.rebuildTrie { - dst.rebuildTrie[i] = true - } - - for fldIdx, fieldTrie := range b.stateFieldLeaves { - dst.stateFieldLeaves[fldIdx] = fieldTrie - if fieldTrie.FieldReference() != nil { - fieldTrie.Lock() - fieldTrie.FieldReference().AddRef() - fieldTrie.Unlock() - } - } - - if b.merkleLayers != nil { - dst.merkleLayers = make([][][]byte, len(b.merkleLayers)) - for i, layer := range b.merkleLayers { - dst.merkleLayers[i] = make([][]byte, len(layer)) - for j, content := range layer { - dst.merkleLayers[i][j] = make([]byte, len(content)) - copy(dst.merkleLayers[i][j], content) - } - } - } - - state.StateCount.Inc() - // Finalizer runs when dst is being destroyed in garbage collection. - runtime.SetFinalizer(dst, func(b *BeaconState) { - for field, v := range b.sharedFieldReferences { - v.MinusRef() - if b.stateFieldLeaves[field].FieldReference() != nil { - b.stateFieldLeaves[field].FieldReference().MinusRef() - } - } - for i := 0; i < fieldCount; i++ { - field := types.FieldIndex(i) - delete(b.stateFieldLeaves, field) - delete(b.dirtyIndices, field) - delete(b.dirtyFields, field) - delete(b.sharedFieldReferences, field) - delete(b.stateFieldLeaves, field) - } - state.StateCount.Sub(1) - }) - - return dst -} - -// HashTreeRoot of the beacon state retrieves the Merkle root of the trie -// representation of the beacon state based on the eth2 Simple Serialize specification. -func (b *BeaconState) HashTreeRoot(ctx context.Context) ([32]byte, error) { - _, span := trace.StartSpan(ctx, "beaconStateAltair.HashTreeRoot") - defer span.End() - - b.lock.Lock() - defer b.lock.Unlock() - if err := b.initializeMerkleLayers(ctx); err != nil { - return [32]byte{}, err - } - if err := b.recomputeDirtyFields(ctx); err != nil { - return [32]byte{}, err - } - return bytesutil.ToBytes32(b.merkleLayers[len(b.merkleLayers)-1][0]), nil -} - -// Initializes the Merkle layers for the beacon state if they are empty. -// WARNING: Caller must acquire the mutex before using. -func (b *BeaconState) initializeMerkleLayers(ctx context.Context) error { - if len(b.merkleLayers) > 0 { - return nil - } - protoState, ok := b.ToProtoUnsafe().(*ethpb.BeaconStateAltair) - if !ok { - return errors.New("state is of the wrong type") - } - fieldRoots, err := computeFieldRoots(ctx, protoState) - if err != nil { - return err - } - layers := stateutil.Merkleize(fieldRoots) - b.merkleLayers = layers - b.dirtyFields = make(map[types.FieldIndex]bool, params.BeaconConfig().BeaconStateAltairFieldCount) - return nil -} - -// Recomputes the Merkle layers for the dirty fields in the state. -// WARNING: Caller must acquire the mutex before using. -func (b *BeaconState) recomputeDirtyFields(ctx context.Context) error { - for field := range b.dirtyFields { - root, err := b.rootSelector(ctx, field) - if err != nil { - return err - } - b.merkleLayers[0][field] = root[:] - b.recomputeRoot(int(field)) - delete(b.dirtyFields, field) - } - return nil -} - -// FieldReferencesCount returns the reference count held by each field. This -// also includes the field trie held by each field. -func (b *BeaconState) FieldReferencesCount() map[string]uint64 { - refMap := make(map[string]uint64) - b.lock.RLock() - defer b.lock.RUnlock() - for i, f := range b.sharedFieldReferences { - refMap[i.String(b.Version())] = uint64(f.Refs()) - } - for i, f := range b.stateFieldLeaves { - numOfRefs := uint64(f.FieldReference().Refs()) - f.RLock() - if !f.Empty() { - refMap[i.String(b.Version())+"_trie"] = numOfRefs - } - f.RUnlock() - } - return refMap -} - -// IsNil checks if the state and the underlying proto -// object are nil. -func (b *BeaconState) IsNil() bool { - return b == nil -} - -func (b *BeaconState) rootSelector(ctx context.Context, field types.FieldIndex) ([32]byte, error) { - _, span := trace.StartSpan(ctx, "beaconState.rootSelector") - defer span.End() - span.AddAttributes(trace.StringAttribute("field", field.String(b.Version()))) - - hasher := hash.CustomSHA256Hasher() - switch field { - case genesisTime: - return ssz.Uint64Root(b.genesisTime), nil - case genesisValidatorsRoot: - return b.genesisValidatorsRoot, nil - case slot: - return ssz.Uint64Root(uint64(b.slot)), nil - case eth1DepositIndex: - return ssz.Uint64Root(b.eth1DepositIndex), nil - case fork: - return ssz.ForkRoot(b.fork) - case latestBlockHeader: - return stateutil.BlockHeaderRoot(b.latestBlockHeader) - case blockRoots: - if b.rebuildTrie[field] { - err := b.resetFieldTrie(field, b.blockRoots, fieldparams.BlockRootsLength) - if err != nil { - return [32]byte{}, err - } - delete(b.rebuildTrie, field) - return b.stateFieldLeaves[field].TrieRoot() - } - return b.recomputeFieldTrie(blockRoots, b.blockRoots) - case stateRoots: - if b.rebuildTrie[field] { - err := b.resetFieldTrie(field, b.stateRoots, fieldparams.StateRootsLength) - if err != nil { - return [32]byte{}, err - } - delete(b.rebuildTrie, field) - return b.stateFieldLeaves[field].TrieRoot() - } - return b.recomputeFieldTrie(stateRoots, b.stateRoots) - case historicalRoots: - hRoots := make([][]byte, len(b.historicalRoots)) - for i := range hRoots { - hRoots[i] = b.historicalRoots[i][:] - } - return ssz.ByteArrayRootWithLimit(hRoots, fieldparams.HistoricalRootsLength) - case eth1Data: - return stateutil.Eth1Root(hasher, b.eth1Data) - case eth1DataVotes: - if b.rebuildTrie[field] { - err := b.resetFieldTrie( - field, - b.eth1DataVotes, - fieldparams.Eth1DataVotesLength, - ) - if err != nil { - return [32]byte{}, err - } - delete(b.rebuildTrie, field) - return b.stateFieldLeaves[field].TrieRoot() - } - return b.recomputeFieldTrie(field, b.eth1DataVotes) - case validators: - if b.rebuildTrie[field] { - err := b.resetFieldTrie(field, b.validators, fieldparams.ValidatorRegistryLimit) - if err != nil { - return [32]byte{}, err - } - delete(b.rebuildTrie, validators) - return b.stateFieldLeaves[field].TrieRoot() - } - return b.recomputeFieldTrie(validators, b.validators) - case balances: - if b.rebuildTrie[field] { - maxBalCap := uint64(fieldparams.ValidatorRegistryLimit) - elemSize := uint64(8) - balLimit := (maxBalCap*elemSize + 31) / 32 - err := b.resetFieldTrie(field, b.balances, balLimit) - if err != nil { - return [32]byte{}, err - } - delete(b.rebuildTrie, field) - return b.stateFieldLeaves[field].TrieRoot() - } - return b.recomputeFieldTrie(balances, b.balances) - case randaoMixes: - if b.rebuildTrie[field] { - err := b.resetFieldTrie(field, b.randaoMixes, fieldparams.RandaoMixesLength) - if err != nil { - return [32]byte{}, err - } - delete(b.rebuildTrie, field) - return b.stateFieldLeaves[field].TrieRoot() - } - return b.recomputeFieldTrie(randaoMixes, b.randaoMixes) - case slashings: - return ssz.SlashingsRoot(b.slashings) - case previousEpochParticipationBits: - return stateutil.ParticipationBitsRoot(b.previousEpochParticipation) - case currentEpochParticipationBits: - return stateutil.ParticipationBitsRoot(b.currentEpochParticipation) - case justificationBits: - return bytesutil.ToBytes32(b.justificationBits), nil - case previousJustifiedCheckpoint: - return ssz.CheckpointRoot(hasher, b.previousJustifiedCheckpoint) - case currentJustifiedCheckpoint: - return ssz.CheckpointRoot(hasher, b.currentJustifiedCheckpoint) - case finalizedCheckpoint: - return ssz.CheckpointRoot(hasher, b.finalizedCheckpoint) - case inactivityScores: - return stateutil.Uint64ListRootWithRegistryLimit(b.inactivityScores) - case currentSyncCommittee: - return stateutil.SyncCommitteeRoot(b.currentSyncCommittee) - case nextSyncCommittee: - return stateutil.SyncCommitteeRoot(b.nextSyncCommittee) - } - return [32]byte{}, errors.New("invalid field index provided") -} - -func (b *BeaconState) recomputeFieldTrie(index types.FieldIndex, elements interface{}) ([32]byte, error) { - fTrie := b.stateFieldLeaves[index] - // We can't lock the trie directly because the trie's variable gets reassigned, - // and therefore we would call Unlock() on a different object. - fTrieMutex := fTrie.RWMutex - if fTrie.FieldReference().Refs() > 1 { - fTrieMutex.Lock() - fTrie.FieldReference().MinusRef() - newTrie := fTrie.CopyTrie() - b.stateFieldLeaves[index] = newTrie - fTrie = newTrie - fTrieMutex.Unlock() - } - // remove duplicate indexes - b.dirtyIndices[index] = slice.SetUint64(b.dirtyIndices[index]) - // sort indexes again - sort.Slice(b.dirtyIndices[index], func(i int, j int) bool { - return b.dirtyIndices[index][i] < b.dirtyIndices[index][j] - }) - root, err := fTrie.RecomputeTrie(b.dirtyIndices[index], elements) - if err != nil { - return [32]byte{}, err - } - b.dirtyIndices[index] = []uint64{} - return root, nil -} - -func (b *BeaconState) resetFieldTrie(index types.FieldIndex, elements interface{}, length uint64) error { - fTrie, err := fieldtrie.NewFieldTrie(index, fieldMap[index], elements, length) - if err != nil { - return err - } - b.stateFieldLeaves[index] = fTrie - b.dirtyIndices[index] = []uint64{} - return nil -} diff --git a/beacon-chain/state/state-native/v2/state_trie_test.go b/beacon-chain/state/state-native/v2/state_trie_test.go deleted file mode 100644 index f8a2f25cb7..0000000000 --- a/beacon-chain/state/state-native/v2/state_trie_test.go +++ /dev/null @@ -1,162 +0,0 @@ -package v2 - -import ( - "strconv" - "sync" - "testing" - - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" - "github.com/prysmaticlabs/prysm/config/params" - "github.com/prysmaticlabs/prysm/encoding/bytesutil" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/testing/assert" - "github.com/prysmaticlabs/prysm/testing/require" -) - -func TestValidatorMap_DistinctCopy(t *testing.T) { - count := uint64(100) - vals := make([]*ethpb.Validator, 0, count) - for i := uint64(1); i < count; i++ { - someRoot := [fieldparams.RootLength]byte{} - someKey := [fieldparams.BLSPubkeyLength]byte{} - copy(someRoot[:], strconv.Itoa(int(i))) - copy(someKey[:], strconv.Itoa(int(i))) - vals = append(vals, ðpb.Validator{ - PublicKey: someKey[:], - WithdrawalCredentials: someRoot[:], - EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, - Slashed: false, - ActivationEligibilityEpoch: 1, - ActivationEpoch: 1, - ExitEpoch: 1, - WithdrawableEpoch: 1, - }) - } - handler := stateutil.NewValMapHandler(vals) - newHandler := handler.Copy() - wantedPubkey := strconv.Itoa(22) - handler.Set(bytesutil.ToBytes48([]byte(wantedPubkey)), 27) - val1, _ := handler.Get(bytesutil.ToBytes48([]byte(wantedPubkey))) - val2, _ := newHandler.Get(bytesutil.ToBytes48([]byte(wantedPubkey))) - assert.NotEqual(t, val1, val2, "Values are supposed to be unequal due to copy") -} - -func TestInitializeFromProto(t *testing.T) { - type test struct { - name string - state *ethpb.BeaconStateAltair - error string - } - initTests := []test{ - { - name: "nil state", - state: nil, - error: "received nil state", - }, - { - name: "nil validators", - state: ðpb.BeaconStateAltair{ - Slot: 4, - Validators: nil, - }, - }, - { - name: "empty state", - state: ðpb.BeaconStateAltair{}, - }, - // TODO: Add full state. Blocked by testutil migration. - } - for _, tt := range initTests { - t.Run(tt.name, func(t *testing.T) { - _, err := InitializeFromProto(tt.state) - if tt.error != "" { - require.ErrorContains(t, tt.error, err) - } else { - require.NoError(t, err) - } - }) - } -} - -func TestBeaconState_NoDeadlock(t *testing.T) { - count := uint64(100) - vals := make([]*ethpb.Validator, 0, count) - for i := uint64(1); i < count; i++ { - someRoot := [32]byte{} - someKey := [fieldparams.BLSPubkeyLength]byte{} - copy(someRoot[:], strconv.Itoa(int(i))) - copy(someKey[:], strconv.Itoa(int(i))) - vals = append(vals, ðpb.Validator{ - PublicKey: someKey[:], - WithdrawalCredentials: someRoot[:], - EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, - Slashed: false, - ActivationEligibilityEpoch: 1, - ActivationEpoch: 1, - ExitEpoch: 1, - WithdrawableEpoch: 1, - }) - } - st, err := InitializeFromProtoUnsafe(ðpb.BeaconStateAltair{ - Validators: vals, - }) - assert.NoError(t, err) - - wg := new(sync.WaitGroup) - - wg.Add(1) - go func() { - // Continuously lock and unlock the state - // by acquiring the lock. - for i := 0; i < 1000; i++ { - for _, f := range st.stateFieldLeaves { - f.Lock() - if f.Empty() { - f.InsertFieldLayer(make([][]*[fieldparams.RootLength]byte, 10)) - } - f.Unlock() - f.FieldReference().AddRef() - } - } - wg.Done() - }() - // Constantly read from the offending portion - // of the code to ensure there is no possible - // recursive read locking. - for i := 0; i < 1000; i++ { - go func() { - _ = st.FieldReferencesCount() - }() - } - // Test will not terminate in the event of a deadlock. - wg.Wait() -} - -func TestInitializeFromProtoUnsafe(t *testing.T) { - type test struct { - name string - state *ethpb.BeaconStateAltair - error string - } - initTests := []test{ - { - name: "nil state", - state: nil, - error: "received nil state", - }, - { - name: "nil validators", - state: ðpb.BeaconStateAltair{ - Slot: 4, - Validators: nil, - }, - }, - { - name: "empty state", - state: ðpb.BeaconStateAltair{}, - }, - // TODO: Add full state. Blocked by testutil migration. - } - _ = initTests -} diff --git a/beacon-chain/state/state-native/v2/types.go b/beacon-chain/state/state-native/v2/types.go deleted file mode 100644 index a02d9549aa..0000000000 --- a/beacon-chain/state/state-native/v2/types.go +++ /dev/null @@ -1,54 +0,0 @@ -package v2 - -import ( - "github.com/prysmaticlabs/prysm/beacon-chain/state/types" - "github.com/prysmaticlabs/prysm/config/params" -) - -func init() { - fieldMap = make(map[types.FieldIndex]types.DataType, params.BeaconConfig().BeaconStateFieldCount) - - // Initialize the fixed sized arrays. - fieldMap[types.BlockRoots] = types.BasicArray - fieldMap[types.StateRoots] = types.BasicArray - fieldMap[types.RandaoMixes] = types.BasicArray - - // Initialize the composite arrays. - fieldMap[types.Eth1DataVotes] = types.CompositeArray - fieldMap[types.Validators] = types.CompositeArray - - // Initialize Compressed Arrays - fieldMap[types.Balances] = types.CompressedArray -} - -// fieldMap keeps track of each field -// to its corresponding data type. -var fieldMap map[types.FieldIndex]types.DataType - -// Field Aliases for values from the types package. -const ( - genesisTime = types.GenesisTime - genesisValidatorsRoot = types.GenesisValidatorsRoot - slot = types.Slot - fork = types.Fork - latestBlockHeader = types.LatestBlockHeader - blockRoots = types.BlockRoots - stateRoots = types.StateRoots - historicalRoots = types.HistoricalRoots - eth1Data = types.Eth1Data - eth1DataVotes = types.Eth1DataVotes - eth1DepositIndex = types.Eth1DepositIndex - validators = types.Validators - balances = types.Balances - randaoMixes = types.RandaoMixes - slashings = types.Slashings - previousEpochParticipationBits = types.PreviousEpochParticipationBits - currentEpochParticipationBits = types.CurrentEpochParticipationBits - justificationBits = types.JustificationBits - previousJustifiedCheckpoint = types.PreviousJustifiedCheckpoint - currentJustifiedCheckpoint = types.CurrentJustifiedCheckpoint - finalizedCheckpoint = types.FinalizedCheckpoint - inactivityScores = types.InactivityScores - currentSyncCommittee = types.CurrentSyncCommittee - nextSyncCommittee = types.NextSyncCommittee -) diff --git a/beacon-chain/state/state-native/v3/BUILD.bazel b/beacon-chain/state/state-native/v3/BUILD.bazel deleted file mode 100644 index 3b54d88ebb..0000000000 --- a/beacon-chain/state/state-native/v3/BUILD.bazel +++ /dev/null @@ -1,120 +0,0 @@ -load("@prysm//tools/go:def.bzl", "go_library", "go_test") -load("//proto:ssz_proto_library.bzl", "ssz_proto_files") -load("//tools:ssz.bzl", "SSZ_DEPS", "ssz_gen_marshal") - -go_library( - name = "go_default_library", - srcs = [ - "deprecated_getters.go", - "deprecated_setters.go", - "field_roots.go", - "getters_block.go", - "getters_checkpoint.go", - "getters_eth1.go", - "getters_misc.go", - "getters_participation.go", - "getters_payload_header.go", - "getters_randao.go", - "getters_state.go", - "getters_sync_committee.go", - "getters_validator.go", - "proofs.go", - "setters_block.go", - "setters_checkpoint.go", - "setters_eth1.go", - "setters_misc.go", - "setters_participation.go", - "setters_payload_header.go", - "setters_randao.go", - "setters_state.go", - "setters_sync_committee.go", - "setters_validator.go", - "state_trie.go", - "types.go", - ":ssz_generated_files", # keep - ] + select({ - "//config:mainnet": ["beacon_state_mainnet.go"], - "//config:minimal": ["beacon_state_minimal.go"], - }), - importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/v3", - visibility = [ - "//beacon-chain:__subpackages__", - "//testing/spectest:__subpackages__", - "//testing/util:__pkg__", - ], - deps = [ - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/fieldtrie:go_default_library", - "//beacon-chain/state/state-native/custom-types:go_default_library", - "//beacon-chain/state/state-native/v1:go_default_library", - "//beacon-chain/state/stateutil:go_default_library", - "//beacon-chain/state/types:go_default_library", - "//config/fieldparams:go_default_library", - "//config/params:go_default_library", - "//consensus-types/primitives:go_default_library", - "//container/slice:go_default_library", - "//crypto/hash:go_default_library", - "//encoding/bytesutil:go_default_library", - "//encoding/ssz:go_default_library", - "//proto/prysm/v1alpha1:go_default_library", - "//runtime/version:go_default_library", - "@com_github_ferranbt_fastssz//:go_default_library", - "@com_github_pkg_errors//:go_default_library", - "@com_github_prysmaticlabs_go_bitfield//:go_default_library", - "@io_opencensus_go//trace:go_default_library", - "@org_golang_google_protobuf//proto:go_default_library", - ], -) - -go_test( - name = "go_default_test", - srcs = [ - "deprecated_getters_test.go", - "deprecated_setters_test.go", - "getters_block_test.go", - "getters_test.go", - "getters_validator_test.go", - "proofs_test.go", - "setters_test.go", - "state_trie_test.go", - ] + select({ - "//config:mainnet": ["beacon_state_mainnet_test.go"], - "//config:minimal": ["beacon_state_minimal_test.go"], - }), - embed = [":go_default_library"], - deps = [ - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/stateutil:go_default_library", - "//beacon-chain/state/testing:go_default_library", - "//beacon-chain/state/types:go_default_library", - "//beacon-chain/state/v3:go_default_library", - "//config/fieldparams:go_default_library", - "//config/params:go_default_library", - "//consensus-types/primitives:go_default_library", - "//container/trie:go_default_library", - "//crypto/bls:go_default_library", - "//encoding/bytesutil:go_default_library", - "//proto/prysm/v1alpha1:go_default_library", - "//testing/assert:go_default_library", - "//testing/require:go_default_library", - "//testing/util:go_default_library", - "@com_github_prysmaticlabs_go_bitfield//:go_default_library", - ], -) - -ssz_gen_marshal( - name = "ssz_generated_files", - srcs = select({ - "//config:mainnet": ["beacon_state_mainnet.go"], - "//config:minimal": ["beacon_state_minimal.go"], - }), - includes = [ - "//beacon-chain/state/state-native/custom-types:go_default_library", - "//config/fieldparams:go_default_library", - "//consensus-types/primitives:go_default_library", - "//proto/prysm/v1alpha1:go_default_library", - ], - objs = [ - "BeaconState[no-htr]", - ], -) diff --git a/beacon-chain/state/state-native/v3/beacon_state_mainnet_test.go b/beacon-chain/state/state-native/v3/beacon_state_mainnet_test.go deleted file mode 100644 index 18599f9ca9..0000000000 --- a/beacon-chain/state/state-native/v3/beacon_state_mainnet_test.go +++ /dev/null @@ -1,87 +0,0 @@ -//go:build !minimal -// +build !minimal - -package v3 - -import ( - "reflect" - "strconv" - "testing" - - fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" - "github.com/prysmaticlabs/prysm/testing/assert" - "github.com/prysmaticlabs/prysm/testing/require" -) - -func TestMainnetSszValuesAgainstFieldParams(t *testing.T) { - // Casting needed to avoid lock copy analyzer issue. - bs := (interface{})(BeaconState{}) - bsType := reflect.TypeOf(bs) - - f, ok := bsType.FieldByName("genesisValidatorsRoot") - require.Equal(t, true, ok, "Required field not found") - v := f.Tag.Get("ssz-size") - assert.Equal(t, strconv.Itoa(fieldparams.RootLength), v) - - f, ok = bsType.FieldByName("blockRoots") - require.Equal(t, true, ok, "Required field not found") - v = f.Tag.Get("ssz-size") - assert.Equal(t, strconv.Itoa(fieldparams.BlockRootsLength)+","+strconv.Itoa(fieldparams.RootLength), v) - - f, ok = bsType.FieldByName("stateRoots") - require.Equal(t, true, ok, "Required field not found") - v = f.Tag.Get("ssz-size") - assert.Equal(t, strconv.Itoa(fieldparams.StateRootsLength)+","+strconv.Itoa(fieldparams.RootLength), v) - - f, ok = bsType.FieldByName("historicalRoots") - require.Equal(t, true, ok, "Required field not found") - v = f.Tag.Get("ssz-size") - assert.Equal(t, "?,"+strconv.Itoa(fieldparams.RootLength), v) - v = f.Tag.Get("ssz-max") - assert.Equal(t, strconv.Itoa(fieldparams.HistoricalRootsLength), v) - - f, ok = bsType.FieldByName("eth1DataVotes") - require.Equal(t, true, ok, "Required field not found") - v = f.Tag.Get("ssz-max") - assert.Equal(t, strconv.Itoa(fieldparams.Eth1DataVotesLength), v) - - f, ok = bsType.FieldByName("validators") - require.Equal(t, true, ok, "Required field not found") - v = f.Tag.Get("ssz-max") - assert.Equal(t, strconv.Itoa(fieldparams.ValidatorRegistryLimit), v) - - f, ok = bsType.FieldByName("balances") - require.Equal(t, true, ok, "Required field not found") - v = f.Tag.Get("ssz-max") - assert.Equal(t, strconv.Itoa(fieldparams.ValidatorRegistryLimit), v) - - f, ok = bsType.FieldByName("randaoMixes") - require.Equal(t, true, ok, "Required field not found") - v = f.Tag.Get("ssz-size") - assert.Equal(t, strconv.Itoa(fieldparams.RandaoMixesLength)+","+strconv.Itoa(fieldparams.RootLength), v) - - f, ok = bsType.FieldByName("slashings") - require.Equal(t, true, ok, "Required field not found") - v = f.Tag.Get("ssz-size") - assert.Equal(t, strconv.Itoa(fieldparams.SlashingsLength), v) - - f, ok = bsType.FieldByName("previousEpochParticipation") - require.Equal(t, true, ok, "Required field not found") - v = f.Tag.Get("ssz-max") - assert.Equal(t, strconv.Itoa(fieldparams.ValidatorRegistryLimit), v) - - f, ok = bsType.FieldByName("currentEpochParticipation") - require.Equal(t, true, ok, "Required field not found") - v = f.Tag.Get("ssz-max") - assert.Equal(t, strconv.Itoa(fieldparams.ValidatorRegistryLimit), v) - - f, ok = bsType.FieldByName("justificationBits") - require.Equal(t, true, ok, "Required field not found") - v = f.Tag.Get("ssz-size") - assert.Equal(t, "1", v) - - f, ok = bsType.FieldByName("inactivityScores") - require.Equal(t, true, ok, "Required field not found") - v = f.Tag.Get("ssz-max") - assert.Equal(t, strconv.Itoa(fieldparams.ValidatorRegistryLimit), v) -} diff --git a/beacon-chain/state/state-native/v3/beacon_state_minimal_test.go b/beacon-chain/state/state-native/v3/beacon_state_minimal_test.go deleted file mode 100644 index bd74072d69..0000000000 --- a/beacon-chain/state/state-native/v3/beacon_state_minimal_test.go +++ /dev/null @@ -1,87 +0,0 @@ -//go:build minimal -// +build minimal - -package v3 - -import ( - "reflect" - "strconv" - "testing" - - fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" - "github.com/prysmaticlabs/prysm/testing/assert" - "github.com/prysmaticlabs/prysm/testing/require" -) - -func TestMinimalSszValuesAgainstFieldParams(t *testing.T) { - // Casting needed to avoid lock copy analyzer issue. - bs := (interface{})(BeaconState{}) - bsType := reflect.TypeOf(bs) - - f, ok := bsType.FieldByName("genesisValidatorsRoot") - require.Equal(t, true, ok, "Required field not found") - v := f.Tag.Get("ssz-size") - assert.Equal(t, strconv.Itoa(fieldparams.RootLength), v) - - f, ok = bsType.FieldByName("blockRoots") - require.Equal(t, true, ok, "Required field not found") - v = f.Tag.Get("ssz-size") - assert.Equal(t, strconv.Itoa(fieldparams.BlockRootsLength)+","+strconv.Itoa(fieldparams.RootLength), v) - - f, ok = bsType.FieldByName("stateRoots") - require.Equal(t, true, ok, "Required field not found") - v = f.Tag.Get("ssz-size") - assert.Equal(t, strconv.Itoa(fieldparams.StateRootsLength)+","+strconv.Itoa(fieldparams.RootLength), v) - - f, ok = bsType.FieldByName("historicalRoots") - require.Equal(t, true, ok, "Required field not found") - v = f.Tag.Get("ssz-size") - assert.Equal(t, "?,"+strconv.Itoa(fieldparams.RootLength), v) - v = f.Tag.Get("ssz-max") - assert.Equal(t, strconv.Itoa(fieldparams.HistoricalRootsLength), v) - - f, ok = bsType.FieldByName("eth1DataVotes") - require.Equal(t, true, ok, "Required field not found") - v = f.Tag.Get("ssz-max") - assert.Equal(t, strconv.Itoa(fieldparams.Eth1DataVotesLength), v) - - f, ok = bsType.FieldByName("validators") - require.Equal(t, true, ok, "Required field not found") - v = f.Tag.Get("ssz-max") - assert.Equal(t, strconv.Itoa(fieldparams.ValidatorRegistryLimit), v) - - f, ok = bsType.FieldByName("balances") - require.Equal(t, true, ok, "Required field not found") - v = f.Tag.Get("ssz-max") - assert.Equal(t, strconv.Itoa(fieldparams.ValidatorRegistryLimit), v) - - f, ok = bsType.FieldByName("randaoMixes") - require.Equal(t, true, ok, "Required field not found") - v = f.Tag.Get("ssz-size") - assert.Equal(t, strconv.Itoa(fieldparams.RandaoMixesLength)+","+strconv.Itoa(fieldparams.RootLength), v) - - f, ok = bsType.FieldByName("slashings") - require.Equal(t, true, ok, "Required field not found") - v = f.Tag.Get("ssz-size") - assert.Equal(t, strconv.Itoa(fieldparams.SlashingsLength), v) - - f, ok = bsType.FieldByName("previousEpochParticipation") - require.Equal(t, true, ok, "Required field not found") - v = f.Tag.Get("ssz-max") - assert.Equal(t, strconv.Itoa(fieldparams.ValidatorRegistryLimit), v) - - f, ok = bsType.FieldByName("currentEpochParticipation") - require.Equal(t, true, ok, "Required field not found") - v = f.Tag.Get("ssz-max") - assert.Equal(t, strconv.Itoa(fieldparams.ValidatorRegistryLimit), v) - - f, ok = bsType.FieldByName("justificationBits") - require.Equal(t, true, ok, "Required field not found") - v = f.Tag.Get("ssz-size") - assert.Equal(t, "1", v) - - f, ok = bsType.FieldByName("inactivityScores") - require.Equal(t, true, ok, "Required field not found") - v = f.Tag.Get("ssz-max") - assert.Equal(t, strconv.Itoa(fieldparams.ValidatorRegistryLimit), v) -} diff --git a/beacon-chain/state/state-native/v3/deprecated_getters.go b/beacon-chain/state/state-native/v3/deprecated_getters.go deleted file mode 100644 index d02110aeb6..0000000000 --- a/beacon-chain/state/state-native/v3/deprecated_getters.go +++ /dev/null @@ -1,16 +0,0 @@ -package v3 - -import ( - "github.com/pkg/errors" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -// PreviousEpochAttestations is not supported for HF1 beacon state. -func (*BeaconState) PreviousEpochAttestations() ([]*ethpb.PendingAttestation, error) { - return nil, errors.New("PreviousEpochAttestations is not supported for version Bellatrix beacon state") -} - -// CurrentEpochAttestations is not supported for HF1 beacon state. -func (*BeaconState) CurrentEpochAttestations() ([]*ethpb.PendingAttestation, error) { - return nil, errors.New("CurrentEpochAttestations is not supported for version Bellatrix beacon state") -} diff --git a/beacon-chain/state/state-native/v3/deprecated_getters_test.go b/beacon-chain/state/state-native/v3/deprecated_getters_test.go deleted file mode 100644 index 0907bc6391..0000000000 --- a/beacon-chain/state/state-native/v3/deprecated_getters_test.go +++ /dev/null @@ -1,19 +0,0 @@ -package v3 - -import ( - "testing" - - "github.com/prysmaticlabs/prysm/testing/require" -) - -func TestBeaconState_CurrentEpochAttestations(t *testing.T) { - s := &BeaconState{} - _, err := s.CurrentEpochAttestations() - require.ErrorContains(t, "CurrentEpochAttestations is not supported for version Bellatrix beacon state", err) -} - -func TestBeaconState_PreviousEpochAttestations(t *testing.T) { - s := &BeaconState{} - _, err := s.PreviousEpochAttestations() - require.ErrorContains(t, "PreviousEpochAttestations is not supported for version Bellatrix beacon state", err) -} diff --git a/beacon-chain/state/state-native/v3/deprecated_setters.go b/beacon-chain/state/state-native/v3/deprecated_setters.go deleted file mode 100644 index 42c8677186..0000000000 --- a/beacon-chain/state/state-native/v3/deprecated_setters.go +++ /dev/null @@ -1,31 +0,0 @@ -package v3 - -import ( - "github.com/pkg/errors" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -// SetPreviousEpochAttestations is not supported for HF1 beacon state. -func (*BeaconState) SetPreviousEpochAttestations(_ []*ethpb.PendingAttestation) error { - return errors.New("SetPreviousEpochAttestations is not supported for version Bellatrix beacon state") -} - -// SetCurrentEpochAttestations is not supported for HF1 beacon state. -func (*BeaconState) SetCurrentEpochAttestations(_ []*ethpb.PendingAttestation) error { - return errors.New("SetCurrentEpochAttestations is not supported for version Bellatrix beacon state") -} - -// AppendCurrentEpochAttestations is not supported for HF1 beacon state. -func (*BeaconState) AppendCurrentEpochAttestations(_ *ethpb.PendingAttestation) error { - return errors.New("AppendCurrentEpochAttestations is not supported for version Bellatrix beacon state") -} - -// AppendPreviousEpochAttestations is not supported for HF1 beacon state. -func (*BeaconState) AppendPreviousEpochAttestations(_ *ethpb.PendingAttestation) error { - return errors.New("AppendPreviousEpochAttestations is not supported for version Bellatrix beacon state") -} - -// RotateAttestations is not supported for HF1 beacon state. -func (*BeaconState) RotateAttestations() error { - return errors.New("RotateAttestations is not supported for version Bellatrix beacon state") -} diff --git a/beacon-chain/state/state-native/v3/deprecated_setters_test.go b/beacon-chain/state/state-native/v3/deprecated_setters_test.go deleted file mode 100644 index 18c338f8bf..0000000000 --- a/beacon-chain/state/state-native/v3/deprecated_setters_test.go +++ /dev/null @@ -1,27 +0,0 @@ -package v3 - -import ( - "testing" - - "github.com/prysmaticlabs/prysm/testing/require" -) - -func TestBeaconState_AppendCurrentEpochAttestations(t *testing.T) { - s := &BeaconState{} - require.ErrorContains(t, "AppendCurrentEpochAttestations is not supported for version Bellatrix beacon state", s.AppendCurrentEpochAttestations(nil)) -} - -func TestBeaconState_AppendPreviousEpochAttestations(t *testing.T) { - s := &BeaconState{} - require.ErrorContains(t, "AppendPreviousEpochAttestations is not supported for version Bellatrix beacon state", s.AppendPreviousEpochAttestations(nil)) -} - -func TestBeaconState_SetCurrentEpochAttestations(t *testing.T) { - s := &BeaconState{} - require.ErrorContains(t, "SetCurrentEpochAttestations is not supported for version Bellatrix beacon state", s.SetCurrentEpochAttestations(nil)) -} - -func TestBeaconState_SetPreviousEpochAttestations(t *testing.T) { - s := &BeaconState{} - require.ErrorContains(t, "SetPreviousEpochAttestations is not supported for version Bellatrix beacon state", s.SetPreviousEpochAttestations(nil)) -} diff --git a/beacon-chain/state/state-native/v3/field_roots.go b/beacon-chain/state/state-native/v3/field_roots.go deleted file mode 100644 index 588c3f36ad..0000000000 --- a/beacon-chain/state/state-native/v3/field_roots.go +++ /dev/null @@ -1,14 +0,0 @@ -package v3 - -import ( - "context" - - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -// computeFieldRoots returns the hash tree root computations of every field in -// the beacon state as a list of 32 byte roots. -func computeFieldRoots(ctx context.Context, state *ethpb.BeaconStateBellatrix) ([][]byte, error) { - return stateutil.ComputeFieldRootsWithHasherBellatrix(ctx, state) -} diff --git a/beacon-chain/state/state-native/v3/generated.ssz.go b/beacon-chain/state/state-native/v3/generated.ssz.go deleted file mode 100644 index 1d2781145a..0000000000 --- a/beacon-chain/state/state-native/v3/generated.ssz.go +++ /dev/null @@ -1,539 +0,0 @@ -// Code generated by fastssz. DO NOT EDIT. -// Hash: 97deb3150a4f1ad869c5578ae80354cea99d9ff122f823c6e78b9f9e1b66c65d -package v3 - -import ( - ssz "github.com/ferranbt/fastssz" - eth2types "github.com/prysmaticlabs/prysm/consensus-types/primitives" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -// MarshalSSZ ssz marshals the BeaconState object -func (b *BeaconState) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(b) -} - -// MarshalSSZTo ssz marshals the BeaconState object to a target array -func (b *BeaconState) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - offset := int(2736633) - - // Field (0) 'genesisTime' - dst = ssz.MarshalUint64(dst, b.genesisTime) - - // Field (1) 'genesisValidatorsRoot' - dst = append(dst, b.genesisValidatorsRoot[:]...) - - // Field (2) 'slot' - dst = ssz.MarshalUint64(dst, uint64(b.slot)) - - // Field (3) 'fork' - if b.fork == nil { - b.fork = new(ethpb.Fork) - } - if dst, err = b.fork.MarshalSSZTo(dst); err != nil { - return - } - - // Field (4) 'latestBlockHeader' - if b.latestBlockHeader == nil { - b.latestBlockHeader = new(ethpb.BeaconBlockHeader) - } - if dst, err = b.latestBlockHeader.MarshalSSZTo(dst); err != nil { - return - } - - // Field (5) 'blockRoots' - for ii := 0; ii < 8192; ii++ { - dst = append(dst, b.blockRoots[ii][:]...) - } - - // Field (6) 'stateRoots' - for ii := 0; ii < 8192; ii++ { - dst = append(dst, b.stateRoots[ii][:]...) - } - - // Offset (7) 'historicalRoots' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.historicalRoots) * 32 - - // Field (8) 'eth1Data' - if b.eth1Data == nil { - b.eth1Data = new(ethpb.Eth1Data) - } - if dst, err = b.eth1Data.MarshalSSZTo(dst); err != nil { - return - } - - // Offset (9) 'eth1DataVotes' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.eth1DataVotes) * 72 - - // Field (10) 'eth1DepositIndex' - dst = ssz.MarshalUint64(dst, b.eth1DepositIndex) - - // Offset (11) 'validators' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.validators) * 121 - - // Offset (12) 'balances' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.balances) * 8 - - // Field (13) 'randaoMixes' - for ii := 0; ii < 65536; ii++ { - dst = append(dst, b.randaoMixes[ii][:]...) - } - - // Field (14) 'slashings' - if len(b.slashings) != 8192 { - err = ssz.ErrVectorLength - return - } - for ii := 0; ii < 8192; ii++ { - dst = ssz.MarshalUint64(dst, b.slashings[ii]) - } - - // Offset (15) 'previousEpochParticipation' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.previousEpochParticipation) - - // Offset (16) 'currentEpochParticipation' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.currentEpochParticipation) - - // Field (17) 'justificationBits' - if len(b.justificationBits) != 1 { - err = ssz.ErrBytesLength - return - } - dst = append(dst, b.justificationBits...) - - // Field (18) 'previousJustifiedCheckpoint' - if b.previousJustifiedCheckpoint == nil { - b.previousJustifiedCheckpoint = new(ethpb.Checkpoint) - } - if dst, err = b.previousJustifiedCheckpoint.MarshalSSZTo(dst); err != nil { - return - } - - // Field (19) 'currentJustifiedCheckpoint' - if b.currentJustifiedCheckpoint == nil { - b.currentJustifiedCheckpoint = new(ethpb.Checkpoint) - } - if dst, err = b.currentJustifiedCheckpoint.MarshalSSZTo(dst); err != nil { - return - } - - // Field (20) 'finalizedCheckpoint' - if b.finalizedCheckpoint == nil { - b.finalizedCheckpoint = new(ethpb.Checkpoint) - } - if dst, err = b.finalizedCheckpoint.MarshalSSZTo(dst); err != nil { - return - } - - // Offset (21) 'inactivityScores' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.inactivityScores) * 8 - - // Field (22) 'currentSyncCommittee' - if b.currentSyncCommittee == nil { - b.currentSyncCommittee = new(ethpb.SyncCommittee) - } - if dst, err = b.currentSyncCommittee.MarshalSSZTo(dst); err != nil { - return - } - - // Field (23) 'nextSyncCommittee' - if b.nextSyncCommittee == nil { - b.nextSyncCommittee = new(ethpb.SyncCommittee) - } - if dst, err = b.nextSyncCommittee.MarshalSSZTo(dst); err != nil { - return - } - - // Offset (24) 'latestExecutionPayloadHeader' - dst = ssz.WriteOffset(dst, offset) - if b.latestExecutionPayloadHeader == nil { - b.latestExecutionPayloadHeader = new(ethpb.ExecutionPayloadHeader) - } - offset += b.latestExecutionPayloadHeader.SizeSSZ() - - // Field (7) 'historicalRoots' - if len(b.historicalRoots) > 16777216 { - err = ssz.ErrListTooBig - return - } - for ii := 0; ii < len(b.historicalRoots); ii++ { - dst = append(dst, b.historicalRoots[ii][:]...) - } - - // Field (9) 'eth1DataVotes' - if len(b.eth1DataVotes) > 2048 { - err = ssz.ErrListTooBig - return - } - for ii := 0; ii < len(b.eth1DataVotes); ii++ { - if dst, err = b.eth1DataVotes[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (11) 'validators' - if len(b.validators) > 1099511627776 { - err = ssz.ErrListTooBig - return - } - for ii := 0; ii < len(b.validators); ii++ { - if dst, err = b.validators[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (12) 'balances' - if len(b.balances) > 1099511627776 { - err = ssz.ErrListTooBig - return - } - for ii := 0; ii < len(b.balances); ii++ { - dst = ssz.MarshalUint64(dst, b.balances[ii]) - } - - // Field (15) 'previousEpochParticipation' - if len(b.previousEpochParticipation) > 1099511627776 { - err = ssz.ErrBytesLength - return - } - dst = append(dst, b.previousEpochParticipation...) - - // Field (16) 'currentEpochParticipation' - if len(b.currentEpochParticipation) > 1099511627776 { - err = ssz.ErrBytesLength - return - } - dst = append(dst, b.currentEpochParticipation...) - - // Field (21) 'inactivityScores' - if len(b.inactivityScores) > 1099511627776 { - err = ssz.ErrListTooBig - return - } - for ii := 0; ii < len(b.inactivityScores); ii++ { - dst = ssz.MarshalUint64(dst, b.inactivityScores[ii]) - } - - // Field (24) 'latestExecutionPayloadHeader' - if dst, err = b.latestExecutionPayloadHeader.MarshalSSZTo(dst); err != nil { - return - } - - return -} - -// UnmarshalSSZ ssz unmarshals the BeaconState object -func (b *BeaconState) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size < 2736633 { - return ssz.ErrSize - } - - tail := buf - var o7, o9, o11, o12, o15, o16, o21, o24 uint64 - - // Field (0) 'genesisTime' - b.genesisTime = ssz.UnmarshallUint64(buf[0:8]) - - // Field (1) 'genesisValidatorsRoot' - copy(b.genesisValidatorsRoot[:], buf[8:40]) - - // Field (2) 'slot' - b.slot = eth2types.Slot(ssz.UnmarshallUint64(buf[40:48])) - - // Field (3) 'fork' - if b.fork == nil { - b.fork = new(ethpb.Fork) - } - if err = b.fork.UnmarshalSSZ(buf[48:64]); err != nil { - return err - } - - // Field (4) 'latestBlockHeader' - if b.latestBlockHeader == nil { - b.latestBlockHeader = new(ethpb.BeaconBlockHeader) - } - if err = b.latestBlockHeader.UnmarshalSSZ(buf[64:176]); err != nil { - return err - } - - // Field (5) 'blockRoots' - - for ii := 0; ii < 8192; ii++ { - copy(b.blockRoots[ii][:], buf[176:262320][ii*32:(ii+1)*32]) - } - - // Field (6) 'stateRoots' - - for ii := 0; ii < 8192; ii++ { - copy(b.stateRoots[ii][:], buf[262320:524464][ii*32:(ii+1)*32]) - } - - // Offset (7) 'historicalRoots' - if o7 = ssz.ReadOffset(buf[524464:524468]); o7 > size { - return ssz.ErrOffset - } - - if o7 < 2736633 { - return ssz.ErrInvalidVariableOffset - } - - // Field (8) 'eth1Data' - if b.eth1Data == nil { - b.eth1Data = new(ethpb.Eth1Data) - } - if err = b.eth1Data.UnmarshalSSZ(buf[524468:524540]); err != nil { - return err - } - - // Offset (9) 'eth1DataVotes' - if o9 = ssz.ReadOffset(buf[524540:524544]); o9 > size || o7 > o9 { - return ssz.ErrOffset - } - - // Field (10) 'eth1DepositIndex' - b.eth1DepositIndex = ssz.UnmarshallUint64(buf[524544:524552]) - - // Offset (11) 'validators' - if o11 = ssz.ReadOffset(buf[524552:524556]); o11 > size || o9 > o11 { - return ssz.ErrOffset - } - - // Offset (12) 'balances' - if o12 = ssz.ReadOffset(buf[524556:524560]); o12 > size || o11 > o12 { - return ssz.ErrOffset - } - - // Field (13) 'randaoMixes' - - for ii := 0; ii < 65536; ii++ { - copy(b.randaoMixes[ii][:], buf[524560:2621712][ii*32:(ii+1)*32]) - } - - // Field (14) 'slashings' - b.slashings = ssz.ExtendUint64(b.slashings, 8192) - for ii := 0; ii < 8192; ii++ { - b.slashings[ii] = ssz.UnmarshallUint64(buf[2621712:2687248][ii*8 : (ii+1)*8]) - } - - // Offset (15) 'previousEpochParticipation' - if o15 = ssz.ReadOffset(buf[2687248:2687252]); o15 > size || o12 > o15 { - return ssz.ErrOffset - } - - // Offset (16) 'currentEpochParticipation' - if o16 = ssz.ReadOffset(buf[2687252:2687256]); o16 > size || o15 > o16 { - return ssz.ErrOffset - } - - // Field (17) 'justificationBits' - if cap(b.justificationBits) == 0 { - b.justificationBits = make([]byte, 0, len(buf[2687256:2687257])) - } - b.justificationBits = append(b.justificationBits, buf[2687256:2687257]...) - - // Field (18) 'previousJustifiedCheckpoint' - if b.previousJustifiedCheckpoint == nil { - b.previousJustifiedCheckpoint = new(ethpb.Checkpoint) - } - if err = b.previousJustifiedCheckpoint.UnmarshalSSZ(buf[2687257:2687297]); err != nil { - return err - } - - // Field (19) 'currentJustifiedCheckpoint' - if b.currentJustifiedCheckpoint == nil { - b.currentJustifiedCheckpoint = new(ethpb.Checkpoint) - } - if err = b.currentJustifiedCheckpoint.UnmarshalSSZ(buf[2687297:2687337]); err != nil { - return err - } - - // Field (20) 'finalizedCheckpoint' - if b.finalizedCheckpoint == nil { - b.finalizedCheckpoint = new(ethpb.Checkpoint) - } - if err = b.finalizedCheckpoint.UnmarshalSSZ(buf[2687337:2687377]); err != nil { - return err - } - - // Offset (21) 'inactivityScores' - if o21 = ssz.ReadOffset(buf[2687377:2687381]); o21 > size || o16 > o21 { - return ssz.ErrOffset - } - - // Field (22) 'currentSyncCommittee' - if b.currentSyncCommittee == nil { - b.currentSyncCommittee = new(ethpb.SyncCommittee) - } - if err = b.currentSyncCommittee.UnmarshalSSZ(buf[2687381:2712005]); err != nil { - return err - } - - // Field (23) 'nextSyncCommittee' - if b.nextSyncCommittee == nil { - b.nextSyncCommittee = new(ethpb.SyncCommittee) - } - if err = b.nextSyncCommittee.UnmarshalSSZ(buf[2712005:2736629]); err != nil { - return err - } - - // Offset (24) 'latestExecutionPayloadHeader' - if o24 = ssz.ReadOffset(buf[2736629:2736633]); o24 > size || o21 > o24 { - return ssz.ErrOffset - } - - // Field (7) 'historicalRoots' - { - buf = tail[o7:o9] - num, err := ssz.DivideInt2(len(buf), 32, 16777216) - if err != nil { - return err - } - b.historicalRoots = make([][32]byte, num) - for ii := 0; ii < num; ii++ { - copy(b.historicalRoots[ii][:], buf[ii*32:(ii+1)*32]) - } - } - - // Field (9) 'eth1DataVotes' - { - buf = tail[o9:o11] - num, err := ssz.DivideInt2(len(buf), 72, 2048) - if err != nil { - return err - } - b.eth1DataVotes = make([]*ethpb.Eth1Data, num) - for ii := 0; ii < num; ii++ { - if b.eth1DataVotes[ii] == nil { - b.eth1DataVotes[ii] = new(ethpb.Eth1Data) - } - if err = b.eth1DataVotes[ii].UnmarshalSSZ(buf[ii*72 : (ii+1)*72]); err != nil { - return err - } - } - } - - // Field (11) 'validators' - { - buf = tail[o11:o12] - num, err := ssz.DivideInt2(len(buf), 121, 1099511627776) - if err != nil { - return err - } - b.validators = make([]*ethpb.Validator, num) - for ii := 0; ii < num; ii++ { - if b.validators[ii] == nil { - b.validators[ii] = new(ethpb.Validator) - } - if err = b.validators[ii].UnmarshalSSZ(buf[ii*121 : (ii+1)*121]); err != nil { - return err - } - } - } - - // Field (12) 'balances' - { - buf = tail[o12:o15] - num, err := ssz.DivideInt2(len(buf), 8, 1099511627776) - if err != nil { - return err - } - b.balances = ssz.ExtendUint64(b.balances, num) - for ii := 0; ii < num; ii++ { - b.balances[ii] = ssz.UnmarshallUint64(buf[ii*8 : (ii+1)*8]) - } - } - - // Field (15) 'previousEpochParticipation' - { - buf = tail[o15:o16] - if len(buf) > 1099511627776 { - return ssz.ErrBytesLength - } - if cap(b.previousEpochParticipation) == 0 { - b.previousEpochParticipation = make([]byte, 0, len(buf)) - } - b.previousEpochParticipation = append(b.previousEpochParticipation, buf...) - } - - // Field (16) 'currentEpochParticipation' - { - buf = tail[o16:o21] - if len(buf) > 1099511627776 { - return ssz.ErrBytesLength - } - if cap(b.currentEpochParticipation) == 0 { - b.currentEpochParticipation = make([]byte, 0, len(buf)) - } - b.currentEpochParticipation = append(b.currentEpochParticipation, buf...) - } - - // Field (21) 'inactivityScores' - { - buf = tail[o21:o24] - num, err := ssz.DivideInt2(len(buf), 8, 1099511627776) - if err != nil { - return err - } - b.inactivityScores = ssz.ExtendUint64(b.inactivityScores, num) - for ii := 0; ii < num; ii++ { - b.inactivityScores[ii] = ssz.UnmarshallUint64(buf[ii*8 : (ii+1)*8]) - } - } - - // Field (24) 'latestExecutionPayloadHeader' - { - buf = tail[o24:] - if b.latestExecutionPayloadHeader == nil { - b.latestExecutionPayloadHeader = new(ethpb.ExecutionPayloadHeader) - } - if err = b.latestExecutionPayloadHeader.UnmarshalSSZ(buf); err != nil { - return err - } - } - return err -} - -// SizeSSZ returns the ssz encoded size in bytes for the BeaconState object -func (b *BeaconState) SizeSSZ() (size int) { - size = 2736633 - - // Field (7) 'historicalRoots' - size += len(b.historicalRoots) * 32 - - // Field (9) 'eth1DataVotes' - size += len(b.eth1DataVotes) * 72 - - // Field (11) 'validators' - size += len(b.validators) * 121 - - // Field (12) 'balances' - size += len(b.balances) * 8 - - // Field (15) 'previousEpochParticipation' - size += len(b.previousEpochParticipation) - - // Field (16) 'currentEpochParticipation' - size += len(b.currentEpochParticipation) - - // Field (21) 'inactivityScores' - size += len(b.inactivityScores) * 8 - - // Field (24) 'latestExecutionPayloadHeader' - if b.latestExecutionPayloadHeader == nil { - b.latestExecutionPayloadHeader = new(ethpb.ExecutionPayloadHeader) - } - size += b.latestExecutionPayloadHeader.SizeSSZ() - - return -} diff --git a/beacon-chain/state/state-native/v3/getters_block.go b/beacon-chain/state/state-native/v3/getters_block.go deleted file mode 100644 index 4033430360..0000000000 --- a/beacon-chain/state/state-native/v3/getters_block.go +++ /dev/null @@ -1,84 +0,0 @@ -package v3 - -import ( - "fmt" - - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -// LatestBlockHeader stored within the beacon state. -func (b *BeaconState) LatestBlockHeader() *ethpb.BeaconBlockHeader { - if b.latestBlockHeader == nil { - return nil - } - - b.lock.RLock() - defer b.lock.RUnlock() - - return b.latestBlockHeaderVal() -} - -// latestBlockHeaderVal stored within the beacon state. -// This assumes that a lock is already held on BeaconState. -func (b *BeaconState) latestBlockHeaderVal() *ethpb.BeaconBlockHeader { - if b.latestBlockHeader == nil { - return nil - } - - hdr := ðpb.BeaconBlockHeader{ - Slot: b.latestBlockHeader.Slot, - ProposerIndex: b.latestBlockHeader.ProposerIndex, - } - - parentRoot := make([]byte, len(b.latestBlockHeader.ParentRoot)) - bodyRoot := make([]byte, len(b.latestBlockHeader.BodyRoot)) - stateRoot := make([]byte, len(b.latestBlockHeader.StateRoot)) - - copy(parentRoot, b.latestBlockHeader.ParentRoot) - copy(bodyRoot, b.latestBlockHeader.BodyRoot) - copy(stateRoot, b.latestBlockHeader.StateRoot) - hdr.ParentRoot = parentRoot - hdr.BodyRoot = bodyRoot - hdr.StateRoot = stateRoot - return hdr -} - -// BlockRoots kept track of in the beacon state. -func (b *BeaconState) BlockRoots() [][]byte { - if b.blockRoots == nil { - return nil - } - - b.lock.RLock() - defer b.lock.RUnlock() - - return b.blockRoots.Slice() -} - -// BlockRootAtIndex retrieves a specific block root based on an -// input index value. -func (b *BeaconState) BlockRootAtIndex(idx uint64) ([]byte, error) { - if b.blockRoots == nil { - return nil, nil - } - - b.lock.RLock() - defer b.lock.RUnlock() - - r, err := b.blockRootAtIndex(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{}, fmt.Errorf("index %d out of range", idx) - } - - return b.blockRoots[idx], nil -} diff --git a/beacon-chain/state/state-native/v3/getters_block_test.go b/beacon-chain/state/state-native/v3/getters_block_test.go deleted file mode 100644 index ddc1bc60ab..0000000000 --- a/beacon-chain/state/state-native/v3/getters_block_test.go +++ /dev/null @@ -1,45 +0,0 @@ -package v3 - -import ( - "testing" - - "github.com/prysmaticlabs/prysm/beacon-chain/state" - testtmpl "github.com/prysmaticlabs/prysm/beacon-chain/state/testing" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -func TestBeaconState_LatestBlockHeader(t *testing.T) { - testtmpl.VerifyBeaconStateLatestBlockHeader( - t, - func() (state.BeaconState, error) { - return InitializeFromProto(ðpb.BeaconStateBellatrix{}) - }, - func(BH *ethpb.BeaconBlockHeader) (state.BeaconState, error) { - return InitializeFromProto(ðpb.BeaconStateBellatrix{LatestBlockHeader: BH}) - }, - ) -} - -func TestBeaconState_BlockRoots(t *testing.T) { - testtmpl.VerifyBeaconStateBlockRootsNative( - t, - func() (state.BeaconState, error) { - return InitializeFromProto(ðpb.BeaconStateBellatrix{}) - }, - func(BR [][]byte) (state.BeaconState, error) { - return InitializeFromProto(ðpb.BeaconStateBellatrix{BlockRoots: BR}) - }, - ) -} - -func TestBeaconState_BlockRootAtIndex(t *testing.T) { - testtmpl.VerifyBeaconStateBlockRootAtIndexNative( - t, - func() (state.BeaconState, error) { - return InitializeFromProto(ðpb.BeaconStateBellatrix{}) - }, - func(BR [][]byte) (state.BeaconState, error) { - return InitializeFromProto(ðpb.BeaconStateBellatrix{BlockRoots: BR}) - }, - ) -} diff --git a/beacon-chain/state/state-native/v3/getters_checkpoint_test.go b/beacon-chain/state/state-native/v3/getters_checkpoint_test.go deleted file mode 100644 index 28eb6d14fa..0000000000 --- a/beacon-chain/state/state-native/v3/getters_checkpoint_test.go +++ /dev/null @@ -1,74 +0,0 @@ -package v3 - -import ( - "testing" - - "github.com/prysmaticlabs/go-bitfield" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - testtmpl "github.com/prysmaticlabs/prysm/beacon-chain/state/testing" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -func TestBeaconState_JustificationBitsNil(t *testing.T) { - testtmpl.VerifyBeaconStateJustificationBitsNil( - t, - func() (state.BeaconState, error) { - return InitializeFromProtoUnsafe(ðpb.BeaconStateBellatrix{}) - }) -} - -func TestBeaconState_JustificationBits(t *testing.T) { - testtmpl.VerifyBeaconStateJustificationBits( - t, - func(bits bitfield.Bitvector4) (state.BeaconState, error) { - return InitializeFromProtoUnsafe(ðpb.BeaconStateBellatrix{JustificationBits: bits}) - }) -} - -func TestBeaconState_PreviousJustifiedCheckpointNil(t *testing.T) { - testtmpl.VerifyBeaconStatePreviousJustifiedCheckpointNil( - t, - func() (state.BeaconState, error) { - return InitializeFromProtoUnsafe(ðpb.BeaconStateBellatrix{}) - }) -} - -func TestBeaconState_PreviousJustifiedCheckpoint(t *testing.T) { - testtmpl.VerifyBeaconStatePreviousJustifiedCheckpoint( - t, - func(cp *ethpb.Checkpoint) (state.BeaconState, error) { - return InitializeFromProtoUnsafe(ðpb.BeaconStateBellatrix{PreviousJustifiedCheckpoint: cp}) - }) -} - -func TestBeaconState_CurrentJustifiedCheckpointNil(t *testing.T) { - testtmpl.VerifyBeaconStateCurrentJustifiedCheckpointNil( - t, - func() (state.BeaconState, error) { - return InitializeFromProtoUnsafe(ðpb.BeaconStateBellatrix{}) - }) -} - -func TestBeaconState_CurrentJustifiedCheckpoint(t *testing.T) { - testtmpl.VerifyBeaconStateCurrentJustifiedCheckpoint( - t, - func(cp *ethpb.Checkpoint) (state.BeaconState, error) { - return InitializeFromProtoUnsafe(ðpb.BeaconStateBellatrix{CurrentJustifiedCheckpoint: cp}) - }) -} - -func TestBeaconState_FinalizedCheckpointNil(t *testing.T) { - testtmpl.VerifyBeaconStateFinalizedCheckpointNil( - t, - func() (state.BeaconState, error) { - return InitializeFromProtoUnsafe(ðpb.BeaconStateBellatrix{}) - }) -} - -func TestBeaconState_FinalizedCheckpoint(t *testing.T) { - testtmpl.VerifyBeaconStateFinalizedCheckpoint( - t, - func(cp *ethpb.Checkpoint) (state.BeaconState, error) { - return InitializeFromProtoUnsafe(ðpb.BeaconStateBellatrix{FinalizedCheckpoint: cp}) - }) -} diff --git a/beacon-chain/state/state-native/v3/getters_misc.go b/beacon-chain/state/state-native/v3/getters_misc.go deleted file mode 100644 index e15f5c2547..0000000000 --- a/beacon-chain/state/state-native/v3/getters_misc.go +++ /dev/null @@ -1,90 +0,0 @@ -package v3 - -import ( - types "github.com/prysmaticlabs/prysm/consensus-types/primitives" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/runtime/version" -) - -// GenesisTime of the beacon state as a uint64. -func (b *BeaconState) GenesisTime() uint64 { - b.lock.RLock() - defer b.lock.RUnlock() - - return b.genesisTime -} - -// GenesisValidatorsRoot of the beacon state. -func (b *BeaconState) GenesisValidatorsRoot() []byte { - b.lock.RLock() - defer b.lock.RUnlock() - - return b.genesisValidatorsRoot[:] -} - -// Version of the beacon state. This method -// is strictly meant to be used without a lock -// internally. -func (_ *BeaconState) Version() int { - return version.Bellatrix -} - -// Slot of the current beacon chain state. -func (b *BeaconState) Slot() types.Slot { - b.lock.RLock() - defer b.lock.RUnlock() - - return b.slot -} - -// Fork version of the beacon chain. -func (b *BeaconState) Fork() *ethpb.Fork { - if b.fork == nil { - return nil - } - - b.lock.RLock() - defer b.lock.RUnlock() - - return b.forkVal() -} - -// forkVal version of the beacon chain. -// This assumes that a lock is already held on BeaconState. -func (b *BeaconState) forkVal() *ethpb.Fork { - if b.fork == nil { - return nil - } - - prevVersion := make([]byte, len(b.fork.PreviousVersion)) - copy(prevVersion, b.fork.PreviousVersion) - currVersion := make([]byte, len(b.fork.CurrentVersion)) - copy(currVersion, b.fork.CurrentVersion) - return ðpb.Fork{ - PreviousVersion: prevVersion, - CurrentVersion: currVersion, - Epoch: b.fork.Epoch, - } -} - -// HistoricalRoots based on epochs stored in the beacon state. -func (b *BeaconState) HistoricalRoots() [][]byte { - if b.historicalRoots == nil { - return nil - } - - b.lock.RLock() - defer b.lock.RUnlock() - - return b.historicalRoots.Slice() -} - -// balancesLength returns the length of the balances slice. -// This assumes that a lock is already held on BeaconState. -func (b *BeaconState) balancesLength() int { - if b.balances == nil { - return 0 - } - - return len(b.balances) -} diff --git a/beacon-chain/state/state-native/v3/getters_state.go b/beacon-chain/state/state-native/v3/getters_state.go deleted file mode 100644 index 7658c4cba0..0000000000 --- a/beacon-chain/state/state-native/v3/getters_state.go +++ /dev/null @@ -1,136 +0,0 @@ -package v3 - -import ( - "fmt" - - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -// ToProtoUnsafe returns the pointer value of the underlying -// beacon state proto object, bypassing immutability. Use with care. -func (b *BeaconState) ToProtoUnsafe() interface{} { - if b == nil { - return nil - } - - gvrCopy := b.genesisValidatorsRoot - - return ðpb.BeaconStateBellatrix{ - GenesisTime: b.genesisTime, - GenesisValidatorsRoot: gvrCopy[:], - Slot: b.slot, - Fork: b.fork, - LatestBlockHeader: b.latestBlockHeader, - BlockRoots: b.blockRoots.Slice(), - StateRoots: b.stateRoots.Slice(), - HistoricalRoots: b.historicalRoots.Slice(), - Eth1Data: b.eth1Data, - Eth1DataVotes: b.eth1DataVotes, - Eth1DepositIndex: b.eth1DepositIndex, - Validators: b.validators, - Balances: b.balances, - RandaoMixes: b.randaoMixes.Slice(), - Slashings: b.slashings, - PreviousEpochParticipation: b.previousEpochParticipation, - CurrentEpochParticipation: b.currentEpochParticipation, - JustificationBits: b.justificationBits, - PreviousJustifiedCheckpoint: b.previousJustifiedCheckpoint, - CurrentJustifiedCheckpoint: b.currentJustifiedCheckpoint, - FinalizedCheckpoint: b.finalizedCheckpoint, - InactivityScores: b.inactivityScores, - CurrentSyncCommittee: b.currentSyncCommittee, - NextSyncCommittee: b.nextSyncCommittee, - LatestExecutionPayloadHeader: b.latestExecutionPayloadHeader, - } -} - -// ToProto the beacon state into a protobuf for usage. -func (b *BeaconState) ToProto() interface{} { - if b == nil { - return nil - } - - b.lock.RLock() - defer b.lock.RUnlock() - - gvrCopy := b.genesisValidatorsRoot - - return ðpb.BeaconStateBellatrix{ - GenesisTime: b.genesisTime, - GenesisValidatorsRoot: gvrCopy[:], - Slot: b.slot, - Fork: b.forkVal(), - LatestBlockHeader: b.latestBlockHeaderVal(), - BlockRoots: b.blockRoots.Slice(), - StateRoots: b.stateRoots.Slice(), - HistoricalRoots: b.historicalRoots.Slice(), - Eth1Data: b.eth1DataVal(), - Eth1DataVotes: b.eth1DataVotesVal(), - Eth1DepositIndex: b.eth1DepositIndex, - Validators: b.validatorsVal(), - Balances: b.balancesVal(), - RandaoMixes: b.randaoMixes.Slice(), - Slashings: b.slashingsVal(), - PreviousEpochParticipation: b.previousEpochParticipationVal(), - CurrentEpochParticipation: b.currentEpochParticipationVal(), - JustificationBits: b.justificationBitsVal(), - PreviousJustifiedCheckpoint: b.previousJustifiedCheckpointVal(), - CurrentJustifiedCheckpoint: b.currentJustifiedCheckpointVal(), - FinalizedCheckpoint: b.finalizedCheckpointVal(), - InactivityScores: b.inactivityScoresVal(), - CurrentSyncCommittee: b.currentSyncCommitteeVal(), - NextSyncCommittee: b.nextSyncCommitteeVal(), - LatestExecutionPayloadHeader: b.latestExecutionPayloadHeaderVal(), - } -} - -// StateRoots kept track of in the beacon state. -func (b *BeaconState) StateRoots() [][]byte { - if b.stateRoots == nil { - return nil - } - - b.lock.RLock() - defer b.lock.RUnlock() - - return b.stateRoots.Slice() -} - -// StateRootAtIndex retrieves a specific state root based on an -// input index value. -func (b *BeaconState) StateRootAtIndex(idx uint64) ([]byte, error) { - if b.stateRoots == nil { - return nil, nil - } - - b.lock.RLock() - defer b.lock.RUnlock() - - r, err := b.stateRootAtIndex(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. -func (b *BeaconState) stateRootAtIndex(idx uint64) ([32]byte, error) { - if uint64(len(b.stateRoots)) <= idx { - return [32]byte{}, fmt.Errorf("index %d out of range", idx) - } - - return b.stateRoots[idx], nil -} - -// InnerStateUnsafe returns the pointer value of the underlying -// beacon state proto object, bypassing immutability. Use with care. -func (b *BeaconState) InnerStateUnsafe() interface{} { - return b.ToProtoUnsafe() -} - -// CloneInnerState the beacon state into a protobuf for usage. -func (b *BeaconState) CloneInnerState() interface{} { - return nil -} diff --git a/beacon-chain/state/state-native/v3/getters_sync_committee.go b/beacon-chain/state/state-native/v3/getters_sync_committee.go deleted file mode 100644 index 9d3bf39b0a..0000000000 --- a/beacon-chain/state/state-native/v3/getters_sync_committee.go +++ /dev/null @@ -1,53 +0,0 @@ -package v3 - -import ( - "github.com/prysmaticlabs/prysm/encoding/bytesutil" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -// currentSyncCommitteeVal of the current sync committee in beacon chain state. -// This assumes that a lock is already held on BeaconState. -func (b *BeaconState) currentSyncCommitteeVal() *ethpb.SyncCommittee { - return CopySyncCommittee(b.currentSyncCommittee) -} - -// nextSyncCommitteeVal of the next sync committee in beacon chain state. -// This assumes that a lock is already held on BeaconState. -func (b *BeaconState) nextSyncCommitteeVal() *ethpb.SyncCommittee { - return CopySyncCommittee(b.nextSyncCommittee) -} - -// CurrentSyncCommittee of the current sync committee in beacon chain state. -func (b *BeaconState) CurrentSyncCommittee() (*ethpb.SyncCommittee, error) { - b.lock.RLock() - defer b.lock.RUnlock() - - if b.currentSyncCommittee == nil { - return nil, nil - } - - return b.currentSyncCommitteeVal(), nil -} - -// NextSyncCommittee of the next sync committee in beacon chain state. -func (b *BeaconState) NextSyncCommittee() (*ethpb.SyncCommittee, error) { - b.lock.RLock() - defer b.lock.RUnlock() - - if b.nextSyncCommittee == nil { - return nil, nil - } - - return b.nextSyncCommitteeVal(), nil -} - -// CopySyncCommittee copies the provided sync committee object. -func CopySyncCommittee(data *ethpb.SyncCommittee) *ethpb.SyncCommittee { - if data == nil { - return nil - } - return ðpb.SyncCommittee{ - Pubkeys: bytesutil.SafeCopy2dBytes(data.Pubkeys), - AggregatePubkey: bytesutil.SafeCopyBytes(data.AggregatePubkey), - } -} diff --git a/beacon-chain/state/state-native/v3/getters_test.go b/beacon-chain/state/state-native/v3/getters_test.go deleted file mode 100644 index 359bf5f9c3..0000000000 --- a/beacon-chain/state/state-native/v3/getters_test.go +++ /dev/null @@ -1,33 +0,0 @@ -package v3 - -import ( - "testing" - - "github.com/prysmaticlabs/prysm/beacon-chain/state" - testtmpl "github.com/prysmaticlabs/prysm/beacon-chain/state/testing" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -func TestBeaconState_SlotDataRace(t *testing.T) { - testtmpl.VerifyBeaconStateSlotDataRace(t, func() (state.BeaconState, error) { - return InitializeFromProto(ðpb.BeaconStateBellatrix{Slot: 1}) - }) -} - -func TestBeaconState_MatchCurrentJustifiedCheckpt(t *testing.T) { - testtmpl.VerifyBeaconStateMatchCurrentJustifiedCheckptNative( - t, - func(cp *ethpb.Checkpoint) (state.BeaconState, error) { - return InitializeFromProto(ðpb.BeaconStateBellatrix{CurrentJustifiedCheckpoint: cp}) - }, - ) -} - -func TestBeaconState_MatchPreviousJustifiedCheckpt(t *testing.T) { - testtmpl.VerifyBeaconStateMatchPreviousJustifiedCheckptNative( - t, - func(cp *ethpb.Checkpoint) (state.BeaconState, error) { - return InitializeFromProto(ðpb.BeaconStateBellatrix{PreviousJustifiedCheckpoint: cp}) - }, - ) -} diff --git a/beacon-chain/state/state-native/v3/getters_validator_test.go b/beacon-chain/state/state-native/v3/getters_validator_test.go deleted file mode 100644 index 9a273bef7e..0000000000 --- a/beacon-chain/state/state-native/v3/getters_validator_test.go +++ /dev/null @@ -1,18 +0,0 @@ -package v3_test - -import ( - "testing" - - "github.com/prysmaticlabs/prysm/beacon-chain/state" - v3 "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/v3" - testtmpl "github.com/prysmaticlabs/prysm/beacon-chain/state/testing" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -func TestBeaconState_ValidatorAtIndexReadOnly_HandlesNilSlice(t *testing.T) { - testtmpl.VerifyBeaconStateValidatorAtIndexReadOnlyHandlesNilSlice(t, func() (state.BeaconState, error) { - return v3.InitializeFromProtoUnsafe(ðpb.BeaconStateBellatrix{ - Validators: nil, - }) - }) -} diff --git a/beacon-chain/state/state-native/v3/proofs_test.go b/beacon-chain/state/state-native/v3/proofs_test.go deleted file mode 100644 index 818bf17dfe..0000000000 --- a/beacon-chain/state/state-native/v3/proofs_test.go +++ /dev/null @@ -1,105 +0,0 @@ -package v3_test - -import ( - "context" - "testing" - - v3 "github.com/prysmaticlabs/prysm/beacon-chain/state/v3" - "github.com/prysmaticlabs/prysm/container/trie" - "github.com/prysmaticlabs/prysm/crypto/bls" - "github.com/prysmaticlabs/prysm/testing/require" - "github.com/prysmaticlabs/prysm/testing/util" -) - -func TestBeaconStateMerkleProofs(t *testing.T) { - ctx := context.Background() - st, _ := util.DeterministicGenesisStateAltair(t, 256) - htr, err := st.HashTreeRoot(ctx) - require.NoError(t, err) - t.Run("current sync committee", func(t *testing.T) { - sc, err := st.CurrentSyncCommittee() - require.NoError(t, err) - - // Verify the Merkle proof. - scRoot, err := sc.HashTreeRoot() - require.NoError(t, err) - proof, err := st.CurrentSyncCommitteeProof(ctx) - require.NoError(t, err) - valid := trie.VerifyMerkleProof(htr[:], scRoot[:], v3.CurrentSyncCommitteeGeneralizedIndex(), proof) - require.Equal(t, true, valid) - }) - t.Run("next sync committee", func(t *testing.T) { - nextSC, err := st.NextSyncCommittee() - require.NoError(t, err) - proof, err := st.NextSyncCommitteeProof(ctx) - require.NoError(t, err) - - // Verify the Merkle proof. - nextSCRoot, err := nextSC.HashTreeRoot() - require.NoError(t, err) - valid := trie.VerifyMerkleProof(htr[:], nextSCRoot[:], v3.NextSyncCommitteeGeneralizedIndex(), proof) - require.Equal(t, true, valid) - - // Edit the sync committee. - privKey, err := bls.RandKey() - require.NoError(t, err) - nextSC.AggregatePubkey = privKey.PublicKey().Marshal() - require.NoError(t, st.SetNextSyncCommittee(nextSC)) - - // Verifying the old Merkle proof for the new value should fail. - nextSCRoot, err = nextSC.HashTreeRoot() - require.NoError(t, err) - valid = trie.VerifyMerkleProof(htr[:], nextSCRoot[:], v3.NextSyncCommitteeGeneralizedIndex(), proof) - require.Equal(t, false, valid) - - // Generating a new, valid proof should pass. - proof, err = st.NextSyncCommitteeProof(ctx) - require.NoError(t, err) - htr, err = st.HashTreeRoot(ctx) - require.NoError(t, err) - valid = trie.VerifyMerkleProof(htr[:], nextSCRoot[:], v3.NextSyncCommitteeGeneralizedIndex(), proof) - require.Equal(t, true, valid) - }) - t.Run("finalized root", func(t *testing.T) { - finalizedRoot := st.FinalizedCheckpoint().Root - - // Verify the Merkle proof. - htr, err = st.HashTreeRoot(ctx) - require.NoError(t, err) - proof, err := st.FinalizedRootProof(ctx) - require.NoError(t, err) - gIndex := v3.FinalizedRootGeneralizedIndex() - valid := trie.VerifyMerkleProof(htr[:], finalizedRoot, gIndex, proof) - require.Equal(t, true, valid) - }) - t.Run("recomputes root on dirty fields", func(t *testing.T) { - currentRoot, err := st.HashTreeRoot(ctx) - require.NoError(t, err) - cpt := st.FinalizedCheckpoint() - require.NoError(t, err) - - // Edit the checkpoint. - cpt.Epoch = 100 - require.NoError(t, st.SetFinalizedCheckpoint(cpt)) - - // Produce a proof for the finalized root. - proof, err := st.FinalizedRootProof(ctx) - require.NoError(t, err) - - // We expect the previous step to have triggered - // a recomputation of dirty fields in the beacon state, resulting - // in a new hash tree root as the finalized checkpoint had previously - // changed and should have been marked as a dirty state field. - // The proof validity should be false for the old root, but true for the new. - finalizedRoot := st.FinalizedCheckpoint().Root - gIndex := v3.FinalizedRootGeneralizedIndex() - valid := trie.VerifyMerkleProof(currentRoot[:], finalizedRoot, gIndex, proof) - require.Equal(t, false, valid) - - newRoot, err := st.HashTreeRoot(ctx) - require.NoError(t, err) - - valid = trie.VerifyMerkleProof(newRoot[:], finalizedRoot, gIndex, proof) - require.Equal(t, true, valid) - }) -} diff --git a/beacon-chain/state/state-native/v3/references_test.go b/beacon-chain/state/state-native/v3/references_test.go deleted file mode 100644 index 575d8a9905..0000000000 --- a/beacon-chain/state/state-native/v3/references_test.go +++ /dev/null @@ -1,229 +0,0 @@ -package v3 - -import ( - "reflect" - "runtime" - "runtime/debug" - "testing" - - "github.com/prysmaticlabs/prysm/beacon-chain/state" - "github.com/prysmaticlabs/prysm/beacon-chain/state/types" - "github.com/prysmaticlabs/prysm/encoding/bytesutil" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/testing/assert" - "github.com/prysmaticlabs/prysm/testing/require" -) - -func TestStateReferenceSharing_Finalizer(t *testing.T) { - // This test showcases the logic on a the RandaoMixes field with the GC finalizer. - - a, err := InitializeFromProtoUnsafe(ðpb.BeaconStateBellatrix{RandaoMixes: [][]byte{[]byte("foo")}}) - require.NoError(t, err) - s, ok := a.(*BeaconState) - require.Equal(t, true, ok) - assert.Equal(t, uint(1), s.sharedFieldReferences[randaoMixes].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), s.sharedFieldReferences[randaoMixes].Refs(), "Expected 2 references to RANDAO mixes") - _ = b - }() - - runtime.GC() // Should run finalizer on object b - assert.Equal(t, uint(1), s.sharedFieldReferences[randaoMixes].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[randaoMixes].Refs(), "Expected 2 shared references to RANDAO mixes") - require.NoError(t, b.UpdateRandaoMixesAtIndex(0, []byte("bar"))) - if b.sharedFieldReferences[randaoMixes].Refs() != 1 || s.sharedFieldReferences[randaoMixes].Refs() != 1 { - t.Error("Expected 1 shared reference to RANDAO mix for both a and b") - } -} - -func TestStateReferenceCopy_NoUnexpectedRootsMutation(t *testing.T) { - root1, root2 := bytesutil.ToBytes32([]byte("foo")), bytesutil.ToBytes32([]byte("bar")) - a, err := InitializeFromProtoUnsafe(ðpb.BeaconStateBellatrix{ - BlockRoots: [][]byte{ - root1[:], - }, - StateRoots: [][]byte{ - root1[:], - }, - }) - require.NoError(t, err) - s, ok := a.(*BeaconState) - require.Equal(t, true, ok) - assertRefCount(t, s, blockRoots, 1) - assertRefCount(t, s, stateRoots, 1) - - // Copy, increases reference count. - copied := a.Copy() - b, ok := copied.(*BeaconState) - require.Equal(t, true, ok) - assertRefCount(t, s, blockRoots, 2) - assertRefCount(t, s, stateRoots, 2) - assertRefCount(t, b, blockRoots, 2) - assertRefCount(t, b, stateRoots, 2) - assert.Equal(t, 8192, len(b.BlockRoots()), "Wrong number of block roots found") - assert.Equal(t, 8192, len(b.StateRoots()), "Wrong number of state roots found") - - // Assert shared state. - blockRootsA := a.BlockRoots() - stateRootsA := a.StateRoots() - blockRootsB := b.BlockRoots() - stateRootsB := b.StateRoots() - if len(blockRootsA) != len(blockRootsB) || len(blockRootsA) < 1 { - t.Errorf("Unexpected number of block roots, want: %v", 1) - } - if len(stateRootsA) != len(stateRootsB) || len(stateRootsA) < 1 { - t.Errorf("Unexpected number of state roots, want: %v", 1) - } - assertValFound(t, blockRootsA, root1[:]) - assertValFound(t, blockRootsB, root1[:]) - assertValFound(t, stateRootsA, root1[:]) - assertValFound(t, stateRootsB, root1[:]) - - // Mutator should only affect calling state: a. - require.NoError(t, a.UpdateBlockRootAtIndex(0, root2)) - require.NoError(t, a.UpdateStateRootAtIndex(0, root2)) - - // 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[:]) - if len(blockRootsA) != len(blockRootsB) || len(blockRootsA) < 1 { - t.Errorf("Unexpected number of block roots, want: %v", 1) - } - if len(stateRootsA) != len(stateRootsB) || len(stateRootsA) < 1 { - t.Errorf("Unexpected number of state roots, want: %v", 1) - } - 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") - - // Copy on write happened, reference counters are reset. - assertRefCount(t, s, blockRoots, 1) - assertRefCount(t, s, stateRoots, 1) - assertRefCount(t, b, blockRoots, 1) - assertRefCount(t, b, stateRoots, 1) -} - -func TestStateReferenceCopy_NoUnexpectedRandaoMutation(t *testing.T) { - - val1, val2 := bytesutil.PadTo([]byte("foo"), 32), bytesutil.PadTo([]byte("bar"), 32) - a, err := InitializeFromProtoUnsafe(ðpb.BeaconStateBellatrix{ - RandaoMixes: [][]byte{ - val1, - }, - }) - require.NoError(t, err) - s, ok := a.(*BeaconState) - require.Equal(t, true, ok) - assertRefCount(t, s, randaoMixes, 1) - - // Copy, increases reference count. - copied := a.Copy() - b, ok := copied.(*BeaconState) - require.Equal(t, true, ok) - assertRefCount(t, s, randaoMixes, 2) - assertRefCount(t, b, randaoMixes, 2) - - // Assert shared state. - mixesA := a.RandaoMixes() - mixesB := b.RandaoMixes() - if len(mixesA) != len(mixesB) || len(mixesA) < 1 { - t.Errorf("Unexpected number of mix values, want: %v", 1) - } - 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). - if len(mixesA) != len(mixesB) || len(mixesA) < 1 { - t.Errorf("Unexpected number of mix values, want: %v", 1) - } - 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, s, randaoMixes, 1) - assertRefCount(t, b, randaoMixes, 1) -} - -func TestValidatorReferences_RemainsConsistent(t *testing.T) { - a, err := InitializeFromProtoUnsafe(ðpb.BeaconStateBellatrix{ - Validators: []*ethpb.Validator{ - {PublicKey: []byte{'A'}}, - {PublicKey: []byte{'B'}}, - {PublicKey: []byte{'C'}}, - {PublicKey: []byte{'D'}}, - {PublicKey: []byte{'E'}}, - }, - }) - require.NoError(t, err) - - // Create a second state. - copied := a.Copy() - b, ok := copied.(*BeaconState) - require.Equal(t, true, ok) - - // Update First Validator. - assert.NoError(t, a.UpdateValidatorAtIndex(0, ðpb.Validator{PublicKey: []byte{'Z'}})) - - assert.DeepNotEqual(t, a.Validators()[0], b.Validators()[0], "validators are equal when they are supposed to be different") - // Modify all validators from copied state. - assert.NoError(t, b.ApplyToEveryValidator(func(idx int, val *ethpb.Validator) (bool, *ethpb.Validator, error) { - return true, ðpb.Validator{PublicKey: []byte{'V'}}, nil - })) - - // Ensure reference is properly accounted for. - assert.NoError(t, a.ReadFromEveryValidator(func(idx int, val state.ReadOnlyValidator) error { - assert.NotEqual(t, bytesutil.ToBytes48([]byte{'V'}), val.PublicKey()) - return nil - })) -} - -// assertRefCount checks whether reference count for a given state -// at a given index is equal to expected amount. -func assertRefCount(t *testing.T, b *BeaconState, idx types.FieldIndex, want uint) { - if cnt := b.sharedFieldReferences[idx].Refs(); cnt != want { - t.Errorf("Unexpected count of references for index %d, want: %v, got: %v", idx, want, cnt) - } -} - -// assertValFound checks whether item with a given value exists in list. -func assertValFound(t *testing.T, vals [][]byte, val []byte) { - for i := range vals { - if reflect.DeepEqual(vals[i], val) { - return - } - } - t.Log(string(debug.Stack())) - t.Fatalf("Expected value not found (%v), want: %v", vals, val) -} - -// assertValNotFound checks whether item with a given value doesn't exist in list. -func assertValNotFound(t *testing.T, vals [][]byte, val []byte) { - for i := range vals { - if reflect.DeepEqual(vals[i], val) { - t.Log(string(debug.Stack())) - t.Errorf("Unexpected value found (%v),: %v", vals, val) - return - } - } -} diff --git a/beacon-chain/state/state-native/v3/setters_block.go b/beacon-chain/state/state-native/v3/setters_block.go deleted file mode 100644 index 3781a13363..0000000000 --- a/beacon-chain/state/state-native/v3/setters_block.go +++ /dev/null @@ -1,67 +0,0 @@ -package v3 - -import ( - "fmt" - - customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -// SetLatestBlockHeader in the beacon state. -func (b *BeaconState) SetLatestBlockHeader(val *ethpb.BeaconBlockHeader) error { - b.lock.Lock() - defer b.lock.Unlock() - - b.latestBlockHeader = ethpb.CopyBeaconBlockHeader(val) - b.markFieldAsDirty(latestBlockHeader) - return nil -} - -// SetBlockRoots for the beacon state. Updates the entire -// list to a new value by overwriting the previous one. -func (b *BeaconState) SetBlockRoots(val [][]byte) error { - b.lock.Lock() - defer b.lock.Unlock() - - b.sharedFieldReferences[blockRoots].MinusRef() - b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1) - - var rootsArr [fieldparams.BlockRootsLength][fieldparams.RootLength]byte - for i := 0; i < len(rootsArr); i++ { - copy(rootsArr[i][:], val[i]) - } - roots := customtypes.BlockRoots(rootsArr) - b.blockRoots = &roots - b.markFieldAsDirty(blockRoots) - b.rebuildTrie[blockRoots] = true - return nil -} - -// UpdateBlockRootAtIndex for the beacon state. Updates the block root -// at a specific index to a new value. -func (b *BeaconState) UpdateBlockRootAtIndex(idx uint64, blockRoot [32]byte) error { - if uint64(len(b.blockRoots)) <= idx { - return fmt.Errorf("invalid index provided %d", idx) - } - b.lock.Lock() - defer b.lock.Unlock() - - r := b.blockRoots - if ref := b.sharedFieldReferences[blockRoots]; ref.Refs() > 1 { - // Copy elements in underlying array by reference. - roots := *b.blockRoots - rootsCopy := roots - r = &rootsCopy - ref.MinusRef() - b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1) - } - - r[idx] = blockRoot - b.blockRoots = r - - b.markFieldAsDirty(blockRoots) - b.addDirtyIndices(blockRoots, []uint64{idx}) - return nil -} diff --git a/beacon-chain/state/state-native/v3/setters_checkpoint.go b/beacon-chain/state/state-native/v3/setters_checkpoint.go deleted file mode 100644 index 5286103be9..0000000000 --- a/beacon-chain/state/state-native/v3/setters_checkpoint.go +++ /dev/null @@ -1,46 +0,0 @@ -package v3 - -import ( - "github.com/prysmaticlabs/go-bitfield" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" -) - -// SetJustificationBits for the beacon state. -func (b *BeaconState) SetJustificationBits(val bitfield.Bitvector4) error { - b.lock.Lock() - defer b.lock.Unlock() - - b.justificationBits = val - b.markFieldAsDirty(justificationBits) - return nil -} - -// SetPreviousJustifiedCheckpoint for the beacon state. -func (b *BeaconState) SetPreviousJustifiedCheckpoint(val *ethpb.Checkpoint) error { - b.lock.Lock() - defer b.lock.Unlock() - - b.previousJustifiedCheckpoint = val - b.markFieldAsDirty(previousJustifiedCheckpoint) - return nil -} - -// SetCurrentJustifiedCheckpoint for the beacon state. -func (b *BeaconState) SetCurrentJustifiedCheckpoint(val *ethpb.Checkpoint) error { - b.lock.Lock() - defer b.lock.Unlock() - - b.currentJustifiedCheckpoint = val - b.markFieldAsDirty(currentJustifiedCheckpoint) - return nil -} - -// SetFinalizedCheckpoint for the beacon state. -func (b *BeaconState) SetFinalizedCheckpoint(val *ethpb.Checkpoint) error { - b.lock.Lock() - defer b.lock.Unlock() - - b.finalizedCheckpoint = val - b.markFieldAsDirty(finalizedCheckpoint) - return nil -} diff --git a/beacon-chain/state/state-native/v3/setters_misc.go b/beacon-chain/state/state-native/v3/setters_misc.go deleted file mode 100644 index 89bce29995..0000000000 --- a/beacon-chain/state/state-native/v3/setters_misc.go +++ /dev/null @@ -1,178 +0,0 @@ -package v3 - -import ( - "github.com/pkg/errors" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - stateTypes "github.com/prysmaticlabs/prysm/beacon-chain/state/types" - fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" - types "github.com/prysmaticlabs/prysm/consensus-types/primitives" - "github.com/prysmaticlabs/prysm/crypto/hash" - "github.com/prysmaticlabs/prysm/encoding/bytesutil" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" - "google.golang.org/protobuf/proto" -) - -// For our setters, we have a field reference counter through -// which we can track shared field references. This helps when -// performing state copies, as we simply copy the reference to the -// field. When we do need to do need to modify these fields, we -// perform a full copy of the field. This is true of most of our -// fields except for the following below. -// 1) BlockRoots -// 2) StateRoots -// 3) Eth1DataVotes -// 4) RandaoMixes -// 5) HistoricalRoots -// 6) CurrentParticipationBits -// 7) PreviousParticipationBits -// -// The fields referred to above are instead copied by reference, where -// we simply copy the reference to the underlying object instead of the -// whole object. This is possible due to how we have structured our state -// as we copy the value on read, so as to ensure the underlying object is -// not mutated while it is being accessed during a state read. - -const ( - // This specifies the limit till which we process all dirty indices for a certain field. - // If we have more dirty indices than the threshold, then we rebuild the whole trie. This - // comes due to the fact that O(alogn) > O(n) beyond a certain value of a. - indicesLimit = 8000 -) - -// SetGenesisTime for the beacon state. -func (b *BeaconState) SetGenesisTime(val uint64) error { - b.lock.Lock() - defer b.lock.Unlock() - - b.genesisTime = val - b.markFieldAsDirty(genesisTime) - return nil -} - -// SetGenesisValidatorsRoot for the beacon state. -func (b *BeaconState) SetGenesisValidatorsRoot(val []byte) error { - b.lock.Lock() - defer b.lock.Unlock() - - if len(val) != fieldparams.RootLength { - return errors.New("incorrect validators root length") - } - b.genesisValidatorsRoot = bytesutil.ToBytes32(val) - b.markFieldAsDirty(genesisValidatorsRoot) - return nil -} - -// SetSlot for the beacon state. -func (b *BeaconState) SetSlot(val types.Slot) error { - b.lock.Lock() - defer b.lock.Unlock() - - b.slot = val - b.markFieldAsDirty(slot) - return nil -} - -// SetFork version for the beacon chain. -func (b *BeaconState) SetFork(val *ethpb.Fork) error { - b.lock.Lock() - defer b.lock.Unlock() - - fk, ok := proto.Clone(val).(*ethpb.Fork) - if !ok { - return errors.New("proto.Clone did not return a fork proto") - } - b.fork = fk - b.markFieldAsDirty(fork) - return nil -} - -// SetHistoricalRoots for the beacon state. Updates the entire -// list to a new value by overwriting the previous one. -func (b *BeaconState) SetHistoricalRoots(val [][]byte) error { - b.lock.Lock() - defer b.lock.Unlock() - - b.sharedFieldReferences[historicalRoots].MinusRef() - b.sharedFieldReferences[historicalRoots] = stateutil.NewRef(1) - - roots := make([][fieldparams.RootLength]byte, len(val)) - for i, r := range val { - copy(roots[i][:], r) - } - b.historicalRoots = roots - b.markFieldAsDirty(historicalRoots) - return nil -} - -// AppendHistoricalRoots for the beacon state. Appends the new value -// to the the end of list. -func (b *BeaconState) AppendHistoricalRoots(root [32]byte) error { - b.lock.Lock() - defer b.lock.Unlock() - - roots := b.historicalRoots - if b.sharedFieldReferences[historicalRoots].Refs() > 1 { - roots = make([][fieldparams.RootLength]byte, len(b.historicalRoots)) - copy(roots, b.historicalRoots) - b.sharedFieldReferences[historicalRoots].MinusRef() - b.sharedFieldReferences[historicalRoots] = stateutil.NewRef(1) - } - - b.historicalRoots = append(roots, root) - b.markFieldAsDirty(historicalRoots) - return nil -} - -// Recomputes the branch up the index in the Merkle trie representation -// of the beacon state. This method performs slice reads and the caller MUST -// hold the lock before calling this method. -func (b *BeaconState) recomputeRoot(idx int) { - hashFunc := hash.CustomSHA256Hasher() - layers := b.merkleLayers - // The merkle tree structure looks as follows: - // [[r1, r2, r3, r4], [parent1, parent2], [root]] - // Using information about the index which changed, idx, we recompute - // only its branch up the tree. - currentIndex := idx - root := b.merkleLayers[0][idx] - for i := 0; i < len(layers)-1; i++ { - isLeft := currentIndex%2 == 0 - neighborIdx := currentIndex ^ 1 - - neighbor := make([]byte, 32) - if layers[i] != nil && len(layers[i]) != 0 && neighborIdx < len(layers[i]) { - neighbor = layers[i][neighborIdx] - } - if isLeft { - parentHash := hashFunc(append(root, neighbor...)) - root = parentHash[:] - } else { - parentHash := hashFunc(append(neighbor, root...)) - root = parentHash[:] - } - parentIdx := currentIndex / 2 - // Update the cached layers at the parent index. - layers[i+1][parentIdx] = root - currentIndex = parentIdx - } - b.merkleLayers = layers -} - -func (b *BeaconState) markFieldAsDirty(field stateTypes.FieldIndex) { - b.dirtyFields[field] = true -} - -// addDirtyIndices adds the relevant dirty field indices, so that they -// can be recomputed. -func (b *BeaconState) addDirtyIndices(index stateTypes.FieldIndex, indices []uint64) { - if b.rebuildTrie[index] { - return - } - totalIndicesLen := len(b.dirtyIndices[index]) + len(indices) - if totalIndicesLen > indicesLimit { - b.rebuildTrie[index] = true - b.dirtyIndices[index] = []uint64{} - } else { - b.dirtyIndices[index] = append(b.dirtyIndices[index], indices...) - } -} diff --git a/beacon-chain/state/state-native/v3/setters_participation.go b/beacon-chain/state/state-native/v3/setters_participation.go deleted file mode 100644 index 5e0f2d736c..0000000000 --- a/beacon-chain/state/state-native/v3/setters_participation.go +++ /dev/null @@ -1,137 +0,0 @@ -package v3 - -import ( - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" -) - -// SetPreviousParticipationBits for the beacon state. Updates the entire -// list to a new value by overwriting the previous one. -func (b *BeaconState) SetPreviousParticipationBits(val []byte) error { - b.lock.Lock() - defer b.lock.Unlock() - - b.sharedFieldReferences[previousEpochParticipationBits].MinusRef() - b.sharedFieldReferences[previousEpochParticipationBits] = stateutil.NewRef(1) - - b.previousEpochParticipation = val - b.markFieldAsDirty(previousEpochParticipationBits) - b.rebuildTrie[previousEpochParticipationBits] = true - return nil -} - -// SetCurrentParticipationBits for the beacon state. Updates the entire -// list to a new value by overwriting the previous one. -func (b *BeaconState) SetCurrentParticipationBits(val []byte) error { - b.lock.Lock() - defer b.lock.Unlock() - - b.sharedFieldReferences[currentEpochParticipationBits].MinusRef() - b.sharedFieldReferences[currentEpochParticipationBits] = stateutil.NewRef(1) - - b.currentEpochParticipation = val - b.markFieldAsDirty(currentEpochParticipationBits) - b.rebuildTrie[currentEpochParticipationBits] = true - return nil -} - -// AppendCurrentParticipationBits for the beacon state. Appends the new value -// to the the end of list. -func (b *BeaconState) AppendCurrentParticipationBits(val byte) error { - b.lock.Lock() - defer b.lock.Unlock() - - participation := b.currentEpochParticipation - if b.sharedFieldReferences[currentEpochParticipationBits].Refs() > 1 { - // Copy elements in underlying array by reference. - participation = make([]byte, len(b.currentEpochParticipation)) - copy(participation, b.currentEpochParticipation) - b.sharedFieldReferences[currentEpochParticipationBits].MinusRef() - b.sharedFieldReferences[currentEpochParticipationBits] = stateutil.NewRef(1) - } - - b.currentEpochParticipation = append(participation, val) - b.markFieldAsDirty(currentEpochParticipationBits) - b.addDirtyIndices(currentEpochParticipationBits, []uint64{uint64(len(b.currentEpochParticipation) - 1)}) - return nil -} - -// AppendPreviousParticipationBits for the beacon state. Appends the new value -// to the the end of list. -func (b *BeaconState) AppendPreviousParticipationBits(val byte) error { - b.lock.Lock() - defer b.lock.Unlock() - - bits := b.previousEpochParticipation - if b.sharedFieldReferences[previousEpochParticipationBits].Refs() > 1 { - bits = make([]byte, len(b.previousEpochParticipation)) - copy(bits, b.previousEpochParticipation) - b.sharedFieldReferences[previousEpochParticipationBits].MinusRef() - b.sharedFieldReferences[previousEpochParticipationBits] = stateutil.NewRef(1) - } - - b.previousEpochParticipation = append(bits, val) - b.markFieldAsDirty(previousEpochParticipationBits) - b.addDirtyIndices(previousEpochParticipationBits, []uint64{uint64(len(b.previousEpochParticipation) - 1)}) - - return nil -} - -// ModifyPreviousParticipationBits modifies the previous participation bitfield via -// the provided mutator function. -func (b *BeaconState) ModifyPreviousParticipationBits(mutator func(val []byte) ([]byte, error)) error { - b.lock.Lock() - - participation := b.previousEpochParticipation - if b.sharedFieldReferences[previousEpochParticipationBits].Refs() > 1 { - // Copy elements in underlying array by reference. - participation = make([]byte, len(b.previousEpochParticipation)) - copy(participation, b.previousEpochParticipation) - b.sharedFieldReferences[previousEpochParticipationBits].MinusRef() - b.sharedFieldReferences[previousEpochParticipationBits] = stateutil.NewRef(1) - } - // Lock is released so that mutator can - // acquire it. - b.lock.Unlock() - - var err error - participation, err = mutator(participation) - if err != nil { - return err - } - b.lock.Lock() - defer b.lock.Unlock() - b.previousEpochParticipation = participation - b.markFieldAsDirty(previousEpochParticipationBits) - b.rebuildTrie[previousEpochParticipationBits] = true - return nil -} - -// ModifyCurrentParticipationBits modifies the current participation bitfield via -// the provided mutator function. -func (b *BeaconState) ModifyCurrentParticipationBits(mutator func(val []byte) ([]byte, error)) error { - b.lock.Lock() - - participation := b.currentEpochParticipation - if b.sharedFieldReferences[currentEpochParticipationBits].Refs() > 1 { - // Copy elements in underlying array by reference. - participation = make([]byte, len(b.currentEpochParticipation)) - copy(participation, b.currentEpochParticipation) - b.sharedFieldReferences[currentEpochParticipationBits].MinusRef() - b.sharedFieldReferences[currentEpochParticipationBits] = stateutil.NewRef(1) - } - // Lock is released so that mutator can - // acquire it. - b.lock.Unlock() - - var err error - participation, err = mutator(participation) - if err != nil { - return err - } - b.lock.Lock() - defer b.lock.Unlock() - b.currentEpochParticipation = participation - b.markFieldAsDirty(currentEpochParticipationBits) - b.rebuildTrie[currentEpochParticipationBits] = true - return nil -} diff --git a/beacon-chain/state/state-native/v3/setters_payload_header.go b/beacon-chain/state/state-native/v3/setters_payload_header.go deleted file mode 100644 index d4a9982512..0000000000 --- a/beacon-chain/state/state-native/v3/setters_payload_header.go +++ /dev/null @@ -1,13 +0,0 @@ -package v3 - -import ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" - -// SetLatestExecutionPayloadHeader for the beacon state. -func (b *BeaconState) SetLatestExecutionPayloadHeader(val *ethpb.ExecutionPayloadHeader) error { - b.lock.Lock() - defer b.lock.Unlock() - - b.latestExecutionPayloadHeader = val - b.markFieldAsDirty(latestExecutionPayloadHeader) - return nil -} diff --git a/beacon-chain/state/state-native/v3/setters_randao.go b/beacon-chain/state/state-native/v3/setters_randao.go deleted file mode 100644 index 456d8572f3..0000000000 --- a/beacon-chain/state/state-native/v3/setters_randao.go +++ /dev/null @@ -1,56 +0,0 @@ -package v3 - -import ( - "github.com/pkg/errors" - customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" - "github.com/prysmaticlabs/prysm/encoding/bytesutil" -) - -// SetRandaoMixes for the beacon state. Updates the entire -// randao mixes to a new value by overwriting the previous one. -func (b *BeaconState) SetRandaoMixes(val [][]byte) error { - b.lock.Lock() - defer b.lock.Unlock() - - b.sharedFieldReferences[randaoMixes].MinusRef() - b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1) - - var mixesArr [fieldparams.RandaoMixesLength][fieldparams.RootLength]byte - for i := 0; i < len(mixesArr); i++ { - copy(mixesArr[i][:], val[i]) - } - mixes := customtypes.RandaoMixes(mixesArr) - b.randaoMixes = &mixes - b.markFieldAsDirty(randaoMixes) - b.rebuildTrie[randaoMixes] = true - return nil -} - -// UpdateRandaoMixesAtIndex for the beacon state. Updates the randao mixes -// at a specific index to a new value. -func (b *BeaconState) UpdateRandaoMixesAtIndex(idx uint64, val []byte) error { - if uint64(len(b.randaoMixes)) <= idx { - return errors.Errorf("invalid index provided %d", idx) - } - b.lock.Lock() - defer b.lock.Unlock() - - mixes := b.randaoMixes - if refs := b.sharedFieldReferences[randaoMixes].Refs(); refs > 1 { - // Copy elements in underlying array by reference. - m := *b.randaoMixes - mCopy := m - mixes = &mCopy - b.sharedFieldReferences[randaoMixes].MinusRef() - b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1) - } - - mixes[idx] = bytesutil.ToBytes32(val) - b.randaoMixes = mixes - b.markFieldAsDirty(randaoMixes) - b.addDirtyIndices(randaoMixes, []uint64{idx}) - - return nil -} diff --git a/beacon-chain/state/state-native/v3/setters_state.go b/beacon-chain/state/state-native/v3/setters_state.go deleted file mode 100644 index f53561869c..0000000000 --- a/beacon-chain/state/state-native/v3/setters_state.go +++ /dev/null @@ -1,60 +0,0 @@ -package v3 - -import ( - "github.com/pkg/errors" - customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" -) - -// SetStateRoots for the beacon state. Updates the state roots -// to a new value by overwriting the previous value. -func (b *BeaconState) SetStateRoots(val [][]byte) error { - b.lock.Lock() - defer b.lock.Unlock() - - b.sharedFieldReferences[stateRoots].MinusRef() - b.sharedFieldReferences[stateRoots] = stateutil.NewRef(1) - - var rootsArr [fieldparams.StateRootsLength][fieldparams.RootLength]byte - for i := 0; i < len(rootsArr); i++ { - copy(rootsArr[i][:], val[i]) - } - roots := customtypes.StateRoots(rootsArr) - b.stateRoots = &roots - b.markFieldAsDirty(stateRoots) - b.rebuildTrie[stateRoots] = true - return nil -} - -// 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 { - b.lock.RLock() - if uint64(len(b.stateRoots)) <= idx { - b.lock.RUnlock() - return errors.Errorf("invalid index provided %d", idx) - } - b.lock.RUnlock() - - b.lock.Lock() - defer b.lock.Unlock() - - // Check if we hold the only reference to the shared state roots slice. - r := b.stateRoots - if ref := b.sharedFieldReferences[stateRoots]; ref.Refs() > 1 { - // Copy elements in underlying array by reference. - roots := *b.stateRoots - rootsCopy := roots - r = &rootsCopy - ref.MinusRef() - b.sharedFieldReferences[stateRoots] = stateutil.NewRef(1) - } - - r[idx] = stateRoot - b.stateRoots = r - - b.markFieldAsDirty(stateRoots) - b.addDirtyIndices(stateRoots, []uint64{idx}) - return nil -} diff --git a/beacon-chain/state/state-native/v3/setters_test.go b/beacon-chain/state/state-native/v3/setters_test.go deleted file mode 100644 index 6ed53aa955..0000000000 --- a/beacon-chain/state/state-native/v3/setters_test.go +++ /dev/null @@ -1,190 +0,0 @@ -package v3 - -import ( - "context" - "strconv" - "testing" - - "github.com/prysmaticlabs/go-bitfield" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - testtmpl "github.com/prysmaticlabs/prysm/beacon-chain/state/testing" - fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" - "github.com/prysmaticlabs/prysm/config/params" - types "github.com/prysmaticlabs/prysm/consensus-types/primitives" - "github.com/prysmaticlabs/prysm/encoding/bytesutil" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/testing/assert" - "github.com/prysmaticlabs/prysm/testing/require" -) - -func TestBeaconState_AppendBalanceWithTrie(t *testing.T) { - count := uint64(100) - vals := make([]*ethpb.Validator, 0, count) - bals := make([]uint64, 0, count) - for i := uint64(1); i < count; i++ { - someRoot := [fieldparams.RootLength]byte{} - someKey := [fieldparams.BLSPubkeyLength]byte{} - copy(someRoot[:], strconv.Itoa(int(i))) - copy(someKey[:], strconv.Itoa(int(i))) - vals = append(vals, ðpb.Validator{ - PublicKey: someKey[:], - WithdrawalCredentials: someRoot[:], - EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, - Slashed: false, - ActivationEligibilityEpoch: 1, - ActivationEpoch: 1, - ExitEpoch: 1, - WithdrawableEpoch: 1, - }) - bals = append(bals, params.BeaconConfig().MaxEffectiveBalance) - } - zeroHash := params.BeaconConfig().ZeroHash - mockblockRoots := make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot) - for i := 0; i < len(mockblockRoots); i++ { - mockblockRoots[i] = zeroHash[:] - } - - mockstateRoots := make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot) - for i := 0; i < len(mockstateRoots); i++ { - mockstateRoots[i] = zeroHash[:] - } - mockrandaoMixes := make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector) - for i := 0; i < len(mockrandaoMixes); i++ { - mockrandaoMixes[i] = zeroHash[:] - } - var pubKeys [][]byte - for i := uint64(0); i < params.BeaconConfig().SyncCommitteeSize; i++ { - pubKeys = append(pubKeys, bytesutil.PadTo([]byte{}, params.BeaconConfig().BLSPubkeyLength)) - } - payload := ðpb.ExecutionPayloadHeader{ - ParentHash: make([]byte, fieldparams.RootLength), - FeeRecipient: make([]byte, 20), - StateRoot: make([]byte, fieldparams.RootLength), - ReceiptsRoot: make([]byte, fieldparams.RootLength), - LogsBloom: make([]byte, 256), - PrevRandao: make([]byte, fieldparams.RootLength), - BaseFeePerGas: bytesutil.PadTo([]byte{1, 2, 3, 4}, fieldparams.RootLength), - BlockHash: make([]byte, fieldparams.RootLength), - TransactionsRoot: make([]byte, fieldparams.RootLength), - } - st, err := InitializeFromProto(ðpb.BeaconStateBellatrix{ - Slot: 1, - GenesisValidatorsRoot: make([]byte, fieldparams.RootLength), - Fork: ðpb.Fork{ - PreviousVersion: make([]byte, 4), - CurrentVersion: make([]byte, 4), - Epoch: 0, - }, - LatestBlockHeader: ðpb.BeaconBlockHeader{ - ParentRoot: make([]byte, fieldparams.RootLength), - StateRoot: make([]byte, fieldparams.RootLength), - BodyRoot: make([]byte, fieldparams.RootLength), - }, - CurrentEpochParticipation: []byte{}, - PreviousEpochParticipation: []byte{}, - Validators: vals, - Balances: bals, - Eth1Data: ðpb.Eth1Data{ - DepositRoot: make([]byte, fieldparams.RootLength), - BlockHash: make([]byte, fieldparams.RootLength), - }, - BlockRoots: mockblockRoots, - StateRoots: mockstateRoots, - RandaoMixes: mockrandaoMixes, - JustificationBits: bitfield.NewBitvector4(), - PreviousJustifiedCheckpoint: ðpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)}, - CurrentJustifiedCheckpoint: ðpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)}, - FinalizedCheckpoint: ðpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)}, - Slashings: make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector), - CurrentSyncCommittee: ðpb.SyncCommittee{ - Pubkeys: pubKeys, - AggregatePubkey: make([]byte, 48), - }, - NextSyncCommittee: ðpb.SyncCommittee{ - Pubkeys: pubKeys, - AggregatePubkey: make([]byte, 48), - }, - LatestExecutionPayloadHeader: payload, - }) - assert.NoError(t, err) - _, err = st.HashTreeRoot(context.Background()) - assert.NoError(t, err) - - for i := 0; i < 100; i++ { - if i%2 == 0 { - assert.NoError(t, st.UpdateBalancesAtIndex(types.ValidatorIndex(i), 1000)) - } - if i%3 == 0 { - assert.NoError(t, st.AppendBalance(1000)) - } - } - _, err = st.HashTreeRoot(context.Background()) - assert.NoError(t, err) - s, ok := st.(*BeaconState) - require.Equal(t, true, ok) - newRt := bytesutil.ToBytes32(s.merkleLayers[0][balances]) - wantedRt, err := stateutil.Uint64ListRootWithRegistryLimit(st.Balances()) - assert.NoError(t, err) - assert.Equal(t, wantedRt, newRt, "state roots are unequal") -} - -func TestBeaconState_ModifyPreviousParticipationBits(t *testing.T) { - testState := createState(200) - testtmpl.VerifyBeaconStateModifyPreviousParticipationField( - t, - func() (state.BeaconState, error) { - return InitializeFromProto(testState) - }, - ) - testtmpl.VerifyBeaconStateModifyPreviousParticipationField_NestedAction( - t, - func() (state.BeaconState, error) { - return InitializeFromProto(testState) - }, - ) -} - -func TestBeaconState_ModifyCurrentParticipationBits(t *testing.T) { - testState := createState(200) - testtmpl.VerifyBeaconStateModifyCurrentParticipationField( - t, - func() (state.BeaconState, error) { - return InitializeFromProto(testState) - }, - ) - testtmpl.VerifyBeaconStateModifyCurrentParticipationField_NestedAction( - t, - func() (state.BeaconState, error) { - return InitializeFromProto(testState) - }, - ) -} - -func createState(count uint64) *ethpb.BeaconStateBellatrix { - vals := make([]*ethpb.Validator, 0, count) - bals := make([]uint64, 0, count) - for i := uint64(0); i < count; i++ { - someRoot := [32]byte{} - someKey := [fieldparams.BLSPubkeyLength]byte{} - copy(someRoot[:], strconv.Itoa(int(i))) - copy(someKey[:], strconv.Itoa(int(i))) - vals = append(vals, ðpb.Validator{ - PublicKey: someKey[:], - WithdrawalCredentials: someRoot[:], - EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, - Slashed: false, - ActivationEligibilityEpoch: 1, - ActivationEpoch: 1, - ExitEpoch: 1, - WithdrawableEpoch: 1, - }) - bals = append(bals, params.BeaconConfig().MaxEffectiveBalance) - } - return ðpb.BeaconStateBellatrix{ - CurrentEpochParticipation: make([]byte, count), - PreviousEpochParticipation: make([]byte, count), - Validators: vals, - Balances: bals, - } -} diff --git a/beacon-chain/state/state-native/v3/state_trie.go b/beacon-chain/state/state-native/v3/state_trie.go deleted file mode 100644 index 384fd680ea..0000000000 --- a/beacon-chain/state/state-native/v3/state_trie.go +++ /dev/null @@ -1,460 +0,0 @@ -package v3 - -import ( - "context" - "runtime" - "sort" - - "github.com/pkg/errors" - - "github.com/prysmaticlabs/prysm/beacon-chain/state" - "github.com/prysmaticlabs/prysm/beacon-chain/state/fieldtrie" - customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - "github.com/prysmaticlabs/prysm/beacon-chain/state/types" - fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" - "github.com/prysmaticlabs/prysm/config/params" - "github.com/prysmaticlabs/prysm/container/slice" - "github.com/prysmaticlabs/prysm/crypto/hash" - "github.com/prysmaticlabs/prysm/encoding/bytesutil" - "github.com/prysmaticlabs/prysm/encoding/ssz" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" - "go.opencensus.io/trace" - "google.golang.org/protobuf/proto" -) - -// InitializeFromProto the beacon state from a protobuf representation. -func InitializeFromProto(st *ethpb.BeaconStateBellatrix) (state.BeaconStateBellatrix, error) { - return InitializeFromProtoUnsafe(proto.Clone(st).(*ethpb.BeaconStateBellatrix)) -} - -// InitializeFromProtoUnsafe directly uses the beacon state protobuf fields -// and sets them as fields of the BeaconState type. -func InitializeFromProtoUnsafe(st *ethpb.BeaconStateBellatrix) (state.BeaconStateBellatrix, error) { - if st == nil { - return nil, errors.New("received nil state") - } - - var bRoots customtypes.BlockRoots - for i, r := range st.BlockRoots { - bRoots[i] = bytesutil.ToBytes32(r) - } - var sRoots customtypes.StateRoots - for i, r := range st.StateRoots { - sRoots[i] = bytesutil.ToBytes32(r) - } - hRoots := customtypes.HistoricalRoots(make([][32]byte, len(st.HistoricalRoots))) - for i, r := range st.HistoricalRoots { - hRoots[i] = bytesutil.ToBytes32(r) - } - var mixes customtypes.RandaoMixes - for i, m := range st.RandaoMixes { - mixes[i] = bytesutil.ToBytes32(m) - } - - fieldCount := params.BeaconConfig().BeaconStateBellatrixFieldCount - b := &BeaconState{ - genesisTime: st.GenesisTime, - genesisValidatorsRoot: bytesutil.ToBytes32(st.GenesisValidatorsRoot), - slot: st.Slot, - fork: st.Fork, - latestBlockHeader: st.LatestBlockHeader, - blockRoots: &bRoots, - stateRoots: &sRoots, - historicalRoots: hRoots, - eth1Data: st.Eth1Data, - eth1DataVotes: st.Eth1DataVotes, - eth1DepositIndex: st.Eth1DepositIndex, - validators: st.Validators, - balances: st.Balances, - randaoMixes: &mixes, - slashings: st.Slashings, - previousEpochParticipation: st.PreviousEpochParticipation, - currentEpochParticipation: st.CurrentEpochParticipation, - justificationBits: st.JustificationBits, - previousJustifiedCheckpoint: st.PreviousJustifiedCheckpoint, - currentJustifiedCheckpoint: st.CurrentJustifiedCheckpoint, - finalizedCheckpoint: st.FinalizedCheckpoint, - inactivityScores: st.InactivityScores, - currentSyncCommittee: st.CurrentSyncCommittee, - nextSyncCommittee: st.NextSyncCommittee, - latestExecutionPayloadHeader: st.LatestExecutionPayloadHeader, - - dirtyFields: make(map[types.FieldIndex]bool, fieldCount), - dirtyIndices: make(map[types.FieldIndex][]uint64, fieldCount), - stateFieldLeaves: make(map[types.FieldIndex]*fieldtrie.FieldTrie, fieldCount), - sharedFieldReferences: make(map[types.FieldIndex]*stateutil.Reference, 11), - rebuildTrie: make(map[types.FieldIndex]bool, fieldCount), - valMapHandler: stateutil.NewValMapHandler(st.Validators), - } - - var err error - for i := 0; i < fieldCount; i++ { - b.dirtyFields[types.FieldIndex(i)] = true - b.rebuildTrie[types.FieldIndex(i)] = true - b.dirtyIndices[types.FieldIndex(i)] = []uint64{} - b.stateFieldLeaves[types.FieldIndex(i)], err = fieldtrie.NewFieldTrie(types.FieldIndex(i), types.BasicArray, nil, 0) - if err != nil { - return nil, err - } - } - - // Initialize field reference tracking for shared data. - b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1) - b.sharedFieldReferences[stateRoots] = stateutil.NewRef(1) - b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1) - b.sharedFieldReferences[previousEpochParticipationBits] = stateutil.NewRef(1) // New in Altair. - b.sharedFieldReferences[currentEpochParticipationBits] = stateutil.NewRef(1) // New in Altair. - b.sharedFieldReferences[slashings] = stateutil.NewRef(1) - b.sharedFieldReferences[eth1DataVotes] = stateutil.NewRef(1) - b.sharedFieldReferences[validators] = stateutil.NewRef(1) - b.sharedFieldReferences[balances] = stateutil.NewRef(1) - b.sharedFieldReferences[inactivityScores] = stateutil.NewRef(1) // New in Altair. - b.sharedFieldReferences[historicalRoots] = stateutil.NewRef(1) - b.sharedFieldReferences[latestExecutionPayloadHeader] = stateutil.NewRef(1) // New in Bellatrix. - state.StateCount.Inc() - return b, nil -} - -// Copy returns a deep copy of the beacon state. -func (b *BeaconState) Copy() state.BeaconState { - b.lock.RLock() - defer b.lock.RUnlock() - fieldCount := params.BeaconConfig().BeaconStateBellatrixFieldCount - - dst := &BeaconState{ - // Primitive types, safe to copy. - genesisTime: b.genesisTime, - slot: b.slot, - eth1DepositIndex: b.eth1DepositIndex, - - // Large arrays, infrequently changed, constant size. - randaoMixes: b.randaoMixes, - stateRoots: b.stateRoots, - blockRoots: b.blockRoots, - slashings: b.slashings, - eth1DataVotes: b.eth1DataVotes, - - // Large arrays, increases over time. - validators: b.validators, - balances: b.balances, - historicalRoots: b.historicalRoots, - previousEpochParticipation: b.previousEpochParticipation, - currentEpochParticipation: b.currentEpochParticipation, - inactivityScores: b.inactivityScores, - - // Everything else, too small to be concerned about, constant size. - genesisValidatorsRoot: b.genesisValidatorsRoot, - fork: b.forkVal(), - latestBlockHeader: b.latestBlockHeaderVal(), - eth1Data: b.eth1DataVal(), - justificationBits: b.justificationBitsVal(), - previousJustifiedCheckpoint: b.previousJustifiedCheckpointVal(), - currentJustifiedCheckpoint: b.currentJustifiedCheckpointVal(), - finalizedCheckpoint: b.finalizedCheckpointVal(), - currentSyncCommittee: b.currentSyncCommitteeVal(), - nextSyncCommittee: b.nextSyncCommitteeVal(), - latestExecutionPayloadHeader: b.latestExecutionPayloadHeaderVal(), - - dirtyFields: make(map[types.FieldIndex]bool, fieldCount), - dirtyIndices: make(map[types.FieldIndex][]uint64, fieldCount), - rebuildTrie: make(map[types.FieldIndex]bool, fieldCount), - sharedFieldReferences: make(map[types.FieldIndex]*stateutil.Reference, 11), - stateFieldLeaves: make(map[types.FieldIndex]*fieldtrie.FieldTrie, fieldCount), - - // Copy on write validator index map. - valMapHandler: b.valMapHandler, - } - - for field, ref := range b.sharedFieldReferences { - ref.AddRef() - dst.sharedFieldReferences[field] = ref - } - - // Increment ref for validator map - b.valMapHandler.AddRef() - - for i := range b.dirtyFields { - dst.dirtyFields[i] = true - } - - for i := range b.dirtyIndices { - indices := make([]uint64, len(b.dirtyIndices[i])) - copy(indices, b.dirtyIndices[i]) - dst.dirtyIndices[i] = indices - } - - for i := range b.rebuildTrie { - dst.rebuildTrie[i] = true - } - - for fldIdx, fieldTrie := range b.stateFieldLeaves { - dst.stateFieldLeaves[fldIdx] = fieldTrie - if fieldTrie.FieldReference() != nil { - fieldTrie.Lock() - fieldTrie.FieldReference().AddRef() - fieldTrie.Unlock() - } - } - - if b.merkleLayers != nil { - dst.merkleLayers = make([][][]byte, len(b.merkleLayers)) - for i, layer := range b.merkleLayers { - dst.merkleLayers[i] = make([][]byte, len(layer)) - for j, content := range layer { - dst.merkleLayers[i][j] = make([]byte, len(content)) - copy(dst.merkleLayers[i][j], content) - } - } - } - state.StateCount.Inc() - // Finalizer runs when dst is being destroyed in garbage collection. - runtime.SetFinalizer(dst, func(b *BeaconState) { - for field, v := range b.sharedFieldReferences { - v.MinusRef() - if b.stateFieldLeaves[field].FieldReference() != nil { - b.stateFieldLeaves[field].FieldReference().MinusRef() - } - } - for i := 0; i < fieldCount; i++ { - field := types.FieldIndex(i) - delete(b.stateFieldLeaves, field) - delete(b.dirtyIndices, field) - delete(b.dirtyFields, field) - delete(b.sharedFieldReferences, field) - delete(b.stateFieldLeaves, field) - } - state.StateCount.Sub(1) - }) - - return dst -} - -// HashTreeRoot of the beacon state retrieves the Merkle root of the trie -// representation of the beacon state based on the eth2 Simple Serialize specification. -func (b *BeaconState) HashTreeRoot(ctx context.Context) ([32]byte, error) { - _, span := trace.StartSpan(ctx, "BeaconStateBellatrix.HashTreeRoot") - defer span.End() - - b.lock.Lock() - defer b.lock.Unlock() - - if err := b.initializeMerkleLayers(ctx); err != nil { - return [fieldparams.RootLength]byte{}, err - } - if err := b.recomputeDirtyFields(ctx); err != nil { - return [fieldparams.RootLength]byte{}, err - } - return bytesutil.ToBytes32(b.merkleLayers[len(b.merkleLayers)-1][0]), nil -} - -// Initializes the Merkle layers for the beacon state if they are empty. -// WARNING: Caller must acquire the mutex before using. -func (b *BeaconState) initializeMerkleLayers(ctx context.Context) error { - if len(b.merkleLayers) > 0 { - return nil - } - protoState, ok := b.ToProtoUnsafe().(*ethpb.BeaconStateBellatrix) - if !ok { - return errors.New("state is of the wrong type") - } - fieldRoots, err := computeFieldRoots(ctx, protoState) - if err != nil { - return err - } - layers := stateutil.Merkleize(fieldRoots) - b.merkleLayers = layers - b.dirtyFields = make(map[types.FieldIndex]bool, params.BeaconConfig().BeaconStateBellatrixFieldCount) - return nil -} - -// Recomputes the Merkle layers for the dirty fields in the state. -// WARNING: Caller must acquire the mutex before using. -func (b *BeaconState) recomputeDirtyFields(_ context.Context) error { - for field := range b.dirtyFields { - root, err := b.rootSelector(field) - if err != nil { - return err - } - b.merkleLayers[0][field] = root[:] - b.recomputeRoot(int(field)) - delete(b.dirtyFields, field) - } - return nil -} - -// FieldReferencesCount returns the reference count held by each field. This -// also includes the field trie held by each field. -func (b *BeaconState) FieldReferencesCount() map[string]uint64 { - refMap := make(map[string]uint64) - b.lock.RLock() - defer b.lock.RUnlock() - for i, f := range b.sharedFieldReferences { - refMap[i.String(b.Version())] = uint64(f.Refs()) - } - for i, f := range b.stateFieldLeaves { - numOfRefs := uint64(f.FieldReference().Refs()) - f.RLock() - if !f.Empty() { - refMap[i.String(b.Version())+"_trie"] = numOfRefs - } - f.RUnlock() - } - return refMap -} - -// IsNil checks if the state and the underlying proto -// object are nil. -func (b *BeaconState) IsNil() bool { - return b == nil -} - -func (b *BeaconState) rootSelector(field types.FieldIndex) ([32]byte, error) { - hasher := hash.CustomSHA256Hasher() - switch field { - case genesisTime: - return ssz.Uint64Root(b.genesisTime), nil - case genesisValidatorsRoot: - return b.genesisValidatorsRoot, nil - case slot: - return ssz.Uint64Root(uint64(b.slot)), nil - case eth1DepositIndex: - return ssz.Uint64Root(b.eth1DepositIndex), nil - case fork: - return ssz.ForkRoot(b.fork) - case latestBlockHeader: - return stateutil.BlockHeaderRoot(b.latestBlockHeader) - case blockRoots: - if b.rebuildTrie[field] { - err := b.resetFieldTrie(field, b.blockRoots, fieldparams.BlockRootsLength) - if err != nil { - return [32]byte{}, err - } - delete(b.rebuildTrie, field) - return b.stateFieldLeaves[field].TrieRoot() - } - return b.recomputeFieldTrie(blockRoots, b.blockRoots) - case stateRoots: - if b.rebuildTrie[field] { - err := b.resetFieldTrie(field, b.stateRoots, fieldparams.StateRootsLength) - if err != nil { - return [32]byte{}, err - } - delete(b.rebuildTrie, field) - return b.stateFieldLeaves[field].TrieRoot() - } - return b.recomputeFieldTrie(stateRoots, b.stateRoots) - case historicalRoots: - hRoots := make([][]byte, len(b.historicalRoots)) - for i := range hRoots { - hRoots[i] = b.historicalRoots[i][:] - } - return ssz.ByteArrayRootWithLimit(hRoots, fieldparams.HistoricalRootsLength) - case eth1Data: - return stateutil.Eth1Root(hasher, b.eth1Data) - case eth1DataVotes: - if b.rebuildTrie[field] { - err := b.resetFieldTrie( - field, - b.eth1DataVotes, - fieldparams.Eth1DataVotesLength, - ) - if err != nil { - return [32]byte{}, err - } - delete(b.rebuildTrie, field) - return b.stateFieldLeaves[field].TrieRoot() - } - return b.recomputeFieldTrie(field, b.eth1DataVotes) - case validators: - if b.rebuildTrie[field] { - err := b.resetFieldTrie(field, b.validators, fieldparams.ValidatorRegistryLimit) - if err != nil { - return [32]byte{}, err - } - delete(b.rebuildTrie, validators) - return b.stateFieldLeaves[field].TrieRoot() - } - return b.recomputeFieldTrie(validators, b.validators) - case balances: - if b.rebuildTrie[field] { - maxBalCap := uint64(fieldparams.ValidatorRegistryLimit) - elemSize := uint64(8) - balLimit := (maxBalCap*elemSize + 31) / 32 - err := b.resetFieldTrie(field, b.balances, balLimit) - if err != nil { - return [32]byte{}, err - } - delete(b.rebuildTrie, field) - return b.stateFieldLeaves[field].TrieRoot() - } - return b.recomputeFieldTrie(balances, b.balances) - case randaoMixes: - if b.rebuildTrie[field] { - err := b.resetFieldTrie(field, b.randaoMixes, fieldparams.RandaoMixesLength) - if err != nil { - return [32]byte{}, err - } - delete(b.rebuildTrie, field) - return b.stateFieldLeaves[field].TrieRoot() - } - return b.recomputeFieldTrie(randaoMixes, b.randaoMixes) - case slashings: - return ssz.SlashingsRoot(b.slashings) - case previousEpochParticipationBits: - return stateutil.ParticipationBitsRoot(b.previousEpochParticipation) - case currentEpochParticipationBits: - return stateutil.ParticipationBitsRoot(b.currentEpochParticipation) - case justificationBits: - return bytesutil.ToBytes32(b.justificationBits), nil - case previousJustifiedCheckpoint: - return ssz.CheckpointRoot(hasher, b.previousJustifiedCheckpoint) - case currentJustifiedCheckpoint: - return ssz.CheckpointRoot(hasher, b.currentJustifiedCheckpoint) - case finalizedCheckpoint: - return ssz.CheckpointRoot(hasher, b.finalizedCheckpoint) - case inactivityScores: - return stateutil.Uint64ListRootWithRegistryLimit(b.inactivityScores) - case currentSyncCommittee: - return stateutil.SyncCommitteeRoot(b.currentSyncCommittee) - case nextSyncCommittee: - return stateutil.SyncCommitteeRoot(b.nextSyncCommittee) - case latestExecutionPayloadHeader: - return b.latestExecutionPayloadHeader.HashTreeRoot() - } - return [32]byte{}, errors.New("invalid field index provided") -} - -func (b *BeaconState) recomputeFieldTrie(index types.FieldIndex, elements interface{}) ([32]byte, error) { - fTrie := b.stateFieldLeaves[index] - if fTrie.FieldReference().Refs() > 1 { - fTrie.Lock() - defer fTrie.Unlock() - fTrie.FieldReference().MinusRef() - newTrie := fTrie.CopyTrie() - b.stateFieldLeaves[index] = newTrie - fTrie = newTrie - } - // remove duplicate indexes - b.dirtyIndices[index] = slice.SetUint64(b.dirtyIndices[index]) - // sort indexes again - sort.Slice(b.dirtyIndices[index], func(i int, j int) bool { - return b.dirtyIndices[index][i] < b.dirtyIndices[index][j] - }) - root, err := fTrie.RecomputeTrie(b.dirtyIndices[index], elements) - if err != nil { - return [32]byte{}, err - } - b.dirtyIndices[index] = []uint64{} - return root, nil -} - -func (b *BeaconState) resetFieldTrie(index types.FieldIndex, elements interface{}, length uint64) error { - fTrie, err := fieldtrie.NewFieldTrie(index, fieldMap[index], elements, length) - if err != nil { - return err - } - b.stateFieldLeaves[index] = fTrie - b.dirtyIndices[index] = []uint64{} - return nil -} diff --git a/beacon-chain/state/state-native/v3/state_trie_test.go b/beacon-chain/state/state-native/v3/state_trie_test.go deleted file mode 100644 index ab7183242f..0000000000 --- a/beacon-chain/state/state-native/v3/state_trie_test.go +++ /dev/null @@ -1,163 +0,0 @@ -package v3 - -import ( - "strconv" - "sync" - "testing" - - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" - "github.com/prysmaticlabs/prysm/config/params" - "github.com/prysmaticlabs/prysm/encoding/bytesutil" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/testing/assert" - "github.com/prysmaticlabs/prysm/testing/require" -) - -func TestValidatorMap_DistinctCopy(t *testing.T) { - count := uint64(100) - vals := make([]*ethpb.Validator, 0, count) - for i := uint64(1); i < count; i++ { - someRoot := [fieldparams.RootLength]byte{} - someKey := [fieldparams.BLSPubkeyLength]byte{} - copy(someRoot[:], strconv.Itoa(int(i))) - copy(someKey[:], strconv.Itoa(int(i))) - vals = append(vals, ðpb.Validator{ - PublicKey: someKey[:], - WithdrawalCredentials: someRoot[:], - EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, - Slashed: false, - ActivationEligibilityEpoch: 1, - ActivationEpoch: 1, - ExitEpoch: 1, - WithdrawableEpoch: 1, - }) - } - handler := stateutil.NewValMapHandler(vals) - newHandler := handler.Copy() - wantedPubkey := strconv.Itoa(22) - handler.Set(bytesutil.ToBytes48([]byte(wantedPubkey)), 27) - val1, _ := handler.Get(bytesutil.ToBytes48([]byte(wantedPubkey))) - val2, _ := newHandler.Get(bytesutil.ToBytes48([]byte(wantedPubkey))) - assert.NotEqual(t, val1, val2, "Values are supposed to be unequal due to copy") -} - -func TestInitializeFromProto(t *testing.T) { - type test struct { - name string - state *ethpb.BeaconStateBellatrix - error string - } - initTests := []test{ - { - name: "nil state", - state: nil, - error: "received nil state", - }, - { - name: "nil validators", - state: ðpb.BeaconStateBellatrix{ - Slot: 4, - Validators: nil, - }, - }, - { - name: "empty state", - state: ðpb.BeaconStateBellatrix{}, - }, - } - for _, tt := range initTests { - t.Run(tt.name, func(t *testing.T) { - _, err := InitializeFromProto(tt.state) - if tt.error != "" { - require.ErrorContains(t, tt.error, err) - } else { - require.NoError(t, err) - } - }) - } -} - -func TestBeaconState_NoDeadlock(t *testing.T) { - count := uint64(100) - vals := make([]*ethpb.Validator, 0, count) - for i := uint64(1); i < count; i++ { - someRoot := [fieldparams.RootLength]byte{} - someKey := [fieldparams.BLSPubkeyLength]byte{} - copy(someRoot[:], strconv.Itoa(int(i))) - copy(someKey[:], strconv.Itoa(int(i))) - vals = append(vals, ðpb.Validator{ - PublicKey: someKey[:], - WithdrawalCredentials: someRoot[:], - EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, - Slashed: false, - ActivationEligibilityEpoch: 1, - ActivationEpoch: 1, - ExitEpoch: 1, - WithdrawableEpoch: 1, - }) - } - st, err := InitializeFromProtoUnsafe(ðpb.BeaconStateBellatrix{ - Validators: vals, - }) - assert.NoError(t, err) - s, ok := st.(*BeaconState) - require.Equal(t, true, ok) - - wg := new(sync.WaitGroup) - - wg.Add(1) - go func() { - // Continuously lock and unlock the state - // by acquiring the lock. - for i := 0; i < 1000; i++ { - for _, f := range s.stateFieldLeaves { - f.Lock() - if f.Empty() { - f.InsertFieldLayer(make([][]*[fieldparams.RootLength]byte, 10)) - } - f.Unlock() - f.FieldReference().AddRef() - } - } - wg.Done() - }() - // Constantly read from the offending portion - // of the code to ensure there is no possible - // recursive read locking. - for i := 0; i < 1000; i++ { - go func() { - _ = st.FieldReferencesCount() - }() - } - // Test will not terminate in the event of a deadlock. - wg.Wait() -} - -func TestInitializeFromProtoUnsafe(t *testing.T) { - type test struct { - name string - state *ethpb.BeaconStateBellatrix - error string - } - initTests := []test{ - { - name: "nil state", - state: nil, - error: "received nil state", - }, - { - name: "nil validators", - state: ðpb.BeaconStateBellatrix{ - Slot: 4, - Validators: nil, - }, - }, - { - name: "empty state", - state: ðpb.BeaconStateBellatrix{}, - }, - // TODO: Add full state. Blocked by testutil migration. - } - _ = initTests -} diff --git a/beacon-chain/state/state-native/v3/types.go b/beacon-chain/state/state-native/v3/types.go deleted file mode 100644 index d4362e0c6d..0000000000 --- a/beacon-chain/state/state-native/v3/types.go +++ /dev/null @@ -1,53 +0,0 @@ -package v3 - -import ( - "github.com/prysmaticlabs/prysm/beacon-chain/state/types" - "github.com/prysmaticlabs/prysm/config/params" -) - -func init() { - fieldMap = make(map[types.FieldIndex]types.DataType, params.BeaconConfig().BeaconStateBellatrixFieldCount) - - // Initialize the fixed sized arrays. - fieldMap[types.BlockRoots] = types.BasicArray - fieldMap[types.StateRoots] = types.BasicArray - fieldMap[types.RandaoMixes] = types.BasicArray - - // Initialize the composite arrays. - fieldMap[types.Eth1DataVotes] = types.CompositeArray - fieldMap[types.Validators] = types.CompositeArray - fieldMap[types.Balances] = types.CompressedArray -} - -// Field Aliases for values from the types package. -const ( - genesisTime = types.GenesisTime - genesisValidatorsRoot = types.GenesisValidatorsRoot - slot = types.Slot - fork = types.Fork - latestBlockHeader = types.LatestBlockHeader - blockRoots = types.BlockRoots - stateRoots = types.StateRoots - historicalRoots = types.HistoricalRoots - eth1Data = types.Eth1Data - eth1DataVotes = types.Eth1DataVotes - eth1DepositIndex = types.Eth1DepositIndex - validators = types.Validators - balances = types.Balances - randaoMixes = types.RandaoMixes - slashings = types.Slashings - previousEpochParticipationBits = types.PreviousEpochParticipationBits - currentEpochParticipationBits = types.CurrentEpochParticipationBits - justificationBits = types.JustificationBits - previousJustifiedCheckpoint = types.PreviousJustifiedCheckpoint - currentJustifiedCheckpoint = types.CurrentJustifiedCheckpoint - finalizedCheckpoint = types.FinalizedCheckpoint - inactivityScores = types.InactivityScores - currentSyncCommittee = types.CurrentSyncCommittee - nextSyncCommittee = types.NextSyncCommittee - latestExecutionPayloadHeader = types.LatestExecutionPayloadHeader -) - -// fieldMap keeps track of each field -// to its corresponding data type. -var fieldMap map[types.FieldIndex]types.DataType diff --git a/beacon-chain/state/stateutil/field_root_attestation.go b/beacon-chain/state/stateutil/field_root_attestation.go index 713dbcce65..ea0de4aa83 100644 --- a/beacon-chain/state/stateutil/field_root_attestation.go +++ b/beacon-chain/state/stateutil/field_root_attestation.go @@ -15,10 +15,10 @@ import ( // RootsArrayHashTreeRoot computes the Merkle root of arrays of 32-byte hashes, such as [64][32]byte // according to the Simple Serialize specification of Ethereum. func RootsArrayHashTreeRoot(vals [][]byte, length uint64) ([32]byte, error) { - return arraysRoot(vals, length) + return ArraysRoot(vals, length) } -func epochAttestationsRoot(atts []*ethpb.PendingAttestation) ([32]byte, error) { +func EpochAttestationsRoot(atts []*ethpb.PendingAttestation) ([32]byte, error) { max := uint64(fieldparams.CurrentEpochAttestationsLength) if uint64(len(atts)) > max { return [32]byte{}, fmt.Errorf("epoch attestation exceeds max length %d", max) diff --git a/beacon-chain/state/stateutil/field_root_eth1.go b/beacon-chain/state/stateutil/field_root_eth1.go index 8f9aebca61..dba431edbe 100644 --- a/beacon-chain/state/stateutil/field_root_eth1.go +++ b/beacon-chain/state/stateutil/field_root_eth1.go @@ -16,9 +16,9 @@ func Eth1Root(hasher ssz.HashFn, eth1Data *ethpb.Eth1Data) ([32]byte, error) { return Eth1DataRootWithHasher(hasher, eth1Data) } -// eth1DataVotesRoot computes the HashTreeRoot Merkleization of +// Eth1DataVotesRoot computes the HashTreeRoot Merkleization of // a list of Eth1Data structs according to the eth2 // Simple Serialize specification. -func eth1DataVotesRoot(eth1DataVotes []*ethpb.Eth1Data) ([32]byte, error) { +func Eth1DataVotesRoot(eth1DataVotes []*ethpb.Eth1Data) ([32]byte, error) { return Eth1DatasRoot(eth1DataVotes) } diff --git a/beacon-chain/state/stateutil/field_root_test.go b/beacon-chain/state/stateutil/field_root_test.go index c5d183ffe5..94f5a2c3e5 100644 --- a/beacon-chain/state/stateutil/field_root_test.go +++ b/beacon-chain/state/stateutil/field_root_test.go @@ -7,17 +7,17 @@ import ( ) func TestArraysTreeRoot_OnlyPowerOf2(t *testing.T) { - _, err := arraysRoot([][]byte{}, 1) + _, err := ArraysRoot([][]byte{}, 1) assert.NoError(t, err) - _, err = arraysRoot([][]byte{}, 4) + _, err = ArraysRoot([][]byte{}, 4) assert.NoError(t, err) - _, err = arraysRoot([][]byte{}, 8) + _, err = ArraysRoot([][]byte{}, 8) assert.NoError(t, err) - _, err = arraysRoot([][]byte{}, 10) + _, err = ArraysRoot([][]byte{}, 10) assert.ErrorContains(t, "hash layer is a non power of 2", err) } func TestArraysTreeRoot_ZeroLength(t *testing.T) { - _, err := arraysRoot([][]byte{}, 0) + _, err := ArraysRoot([][]byte{}, 0) assert.ErrorContains(t, "zero leaves provided", err) } diff --git a/beacon-chain/state/stateutil/field_root_vector.go b/beacon-chain/state/stateutil/field_root_vector.go index 41b8a19664..f2f28d45da 100644 --- a/beacon-chain/state/stateutil/field_root_vector.go +++ b/beacon-chain/state/stateutil/field_root_vector.go @@ -6,7 +6,7 @@ import ( "github.com/prysmaticlabs/prysm/encoding/ssz" ) -func arraysRoot(input [][]byte, length uint64) ([32]byte, error) { +func ArraysRoot(input [][]byte, length uint64) ([32]byte, error) { hashFunc := hash.CustomSHA256Hasher() leaves := make([][32]byte, length) diff --git a/beacon-chain/state/stateutil/state_hasher.go b/beacon-chain/state/stateutil/state_hasher.go index fbf9089bec..f8cdc7ca38 100644 --- a/beacon-chain/state/stateutil/state_hasher.go +++ b/beacon-chain/state/stateutil/state_hasher.go @@ -53,14 +53,14 @@ func ComputeFieldRootsWithHasherPhase0(ctx context.Context, state *ethpb.BeaconS fieldRoots[4] = headerHashTreeRoot[:] // BlockRoots array root. - blockRootsRoot, err := arraysRoot(state.BlockRoots, fieldparams.BlockRootsLength) + blockRootsRoot, err := ArraysRoot(state.BlockRoots, fieldparams.BlockRootsLength) if err != nil { return nil, errors.Wrap(err, "could not compute block roots merkleization") } fieldRoots[5] = blockRootsRoot[:] // StateRoots array root. - stateRootsRoot, err := arraysRoot(state.StateRoots, fieldparams.StateRootsLength) + stateRootsRoot, err := ArraysRoot(state.StateRoots, fieldparams.StateRootsLength) if err != nil { return nil, errors.Wrap(err, "could not compute state roots merkleization") } @@ -81,7 +81,7 @@ func ComputeFieldRootsWithHasherPhase0(ctx context.Context, state *ethpb.BeaconS fieldRoots[8] = eth1HashTreeRoot[:] // Eth1DataVotes slice root. - eth1VotesRoot, err := eth1DataVotesRoot(state.Eth1DataVotes) + eth1VotesRoot, err := Eth1DataVotesRoot(state.Eth1DataVotes) if err != nil { return nil, errors.Wrap(err, "could not compute eth1data votes merkleization") } @@ -108,7 +108,7 @@ func ComputeFieldRootsWithHasherPhase0(ctx context.Context, state *ethpb.BeaconS fieldRoots[12] = balancesRoot[:] // RandaoMixes array root. - randaoRootsRoot, err := arraysRoot(state.RandaoMixes, fieldparams.RandaoMixesLength) + randaoRootsRoot, err := ArraysRoot(state.RandaoMixes, fieldparams.RandaoMixesLength) if err != nil { return nil, errors.Wrap(err, "could not compute randao roots merkleization") } @@ -122,14 +122,14 @@ func ComputeFieldRootsWithHasherPhase0(ctx context.Context, state *ethpb.BeaconS fieldRoots[14] = slashingsRootsRoot[:] // PreviousEpochAttestations slice root. - prevAttsRoot, err := epochAttestationsRoot(state.PreviousEpochAttestations) + prevAttsRoot, err := EpochAttestationsRoot(state.PreviousEpochAttestations) if err != nil { return nil, errors.Wrap(err, "could not compute previous epoch attestations merkleization") } fieldRoots[15] = prevAttsRoot[:] // CurrentEpochAttestations slice root. - currAttsRoot, err := epochAttestationsRoot(state.CurrentEpochAttestations) + currAttsRoot, err := EpochAttestationsRoot(state.CurrentEpochAttestations) if err != nil { return nil, errors.Wrap(err, "could not compute current epoch attestations merkleization") } @@ -201,14 +201,14 @@ func ComputeFieldRootsWithHasherAltair(ctx context.Context, state *ethpb.BeaconS fieldRoots[4] = headerHashTreeRoot[:] // BlockRoots array root. - blockRootsRoot, err := arraysRoot(state.BlockRoots, fieldparams.BlockRootsLength) + blockRootsRoot, err := ArraysRoot(state.BlockRoots, fieldparams.BlockRootsLength) if err != nil { return nil, errors.Wrap(err, "could not compute block roots merkleization") } fieldRoots[5] = blockRootsRoot[:] // StateRoots array root. - stateRootsRoot, err := arraysRoot(state.StateRoots, fieldparams.StateRootsLength) + stateRootsRoot, err := ArraysRoot(state.StateRoots, fieldparams.StateRootsLength) if err != nil { return nil, errors.Wrap(err, "could not compute state roots merkleization") } @@ -229,7 +229,7 @@ func ComputeFieldRootsWithHasherAltair(ctx context.Context, state *ethpb.BeaconS fieldRoots[8] = eth1HashTreeRoot[:] // Eth1DataVotes slice root. - eth1VotesRoot, err := eth1DataVotesRoot(state.Eth1DataVotes) + eth1VotesRoot, err := Eth1DataVotesRoot(state.Eth1DataVotes) if err != nil { return nil, errors.Wrap(err, "could not compute eth1data votes merkleization") } @@ -256,7 +256,7 @@ func ComputeFieldRootsWithHasherAltair(ctx context.Context, state *ethpb.BeaconS fieldRoots[12] = balancesRoot[:] // RandaoMixes array root. - randaoRootsRoot, err := arraysRoot(state.RandaoMixes, fieldparams.RandaoMixesLength) + randaoRootsRoot, err := ArraysRoot(state.RandaoMixes, fieldparams.RandaoMixesLength) if err != nil { return nil, errors.Wrap(err, "could not compute randao roots merkleization") } @@ -371,14 +371,14 @@ func ComputeFieldRootsWithHasherBellatrix(ctx context.Context, state *ethpb.Beac fieldRoots[4] = headerHashTreeRoot[:] // BlockRoots array root. - blockRootsRoot, err := arraysRoot(state.BlockRoots, fieldparams.BlockRootsLength) + blockRootsRoot, err := ArraysRoot(state.BlockRoots, fieldparams.BlockRootsLength) if err != nil { return nil, errors.Wrap(err, "could not compute block roots merkleization") } fieldRoots[5] = blockRootsRoot[:] // StateRoots array root. - stateRootsRoot, err := arraysRoot(state.StateRoots, fieldparams.StateRootsLength) + stateRootsRoot, err := ArraysRoot(state.StateRoots, fieldparams.StateRootsLength) if err != nil { return nil, errors.Wrap(err, "could not compute state roots merkleization") } @@ -399,7 +399,7 @@ func ComputeFieldRootsWithHasherBellatrix(ctx context.Context, state *ethpb.Beac fieldRoots[8] = eth1HashTreeRoot[:] // Eth1DataVotes slice root. - eth1VotesRoot, err := eth1DataVotesRoot(state.Eth1DataVotes) + eth1VotesRoot, err := Eth1DataVotesRoot(state.Eth1DataVotes) if err != nil { return nil, errors.Wrap(err, "could not compute eth1data votes merkleization") } @@ -426,7 +426,7 @@ func ComputeFieldRootsWithHasherBellatrix(ctx context.Context, state *ethpb.Beac fieldRoots[12] = balancesRoot[:] // RandaoMixes array root. - randaoRootsRoot, err := arraysRoot(state.RandaoMixes, fieldparams.RandaoMixesLength) + randaoRootsRoot, err := ArraysRoot(state.RandaoMixes, fieldparams.RandaoMixesLength) if err != nil { return nil, errors.Wrap(err, "could not compute randao roots merkleization") } diff --git a/beacon-chain/state/testing/getters.go b/beacon-chain/state/testing/getters.go index 252dfce799..7493b0420a 100644 --- a/beacon-chain/state/testing/getters.go +++ b/beacon-chain/state/testing/getters.go @@ -89,6 +89,13 @@ func VerifyBeaconStateMarshalSSZNilState(t *testing.T, factory getState, clear c require.ErrorContains(t, "nil beacon state", err) } +func VerifyBeaconStateMarshalSSZNilStateNative(t *testing.T, factory getState) { + s, err := factory() + require.NoError(t, err) + _, err = s.MarshalSSZ() + require.ErrorContains(t, "nil beacon state", err) +} + func VerifyBeaconStateValidatorByPubkey(t *testing.T, factory getState) { keyCreator := func(input []byte) [fieldparams.BLSPubkeyLength]byte { nKey := [fieldparams.BLSPubkeyLength]byte{} diff --git a/beacon-chain/state/testing/getters_checkpoint.go b/beacon-chain/state/testing/getters_checkpoint.go index 9f2aaf700b..16c1929de6 100644 --- a/beacon-chain/state/testing/getters_checkpoint.go +++ b/beacon-chain/state/testing/getters_checkpoint.go @@ -14,9 +14,7 @@ import ( func VerifyBeaconStateJustificationBitsNil(t *testing.T, factory getState) { s, err := factory() require.NoError(t, err) - - bits := s.JustificationBits() - require.DeepEqual(t, bitfield.Bitvector4{}.Bytes(), bits.Bytes()) + require.DeepEqual(t, bitfield.Bitvector4{}.Bytes(), s.JustificationBits().Bytes()) } type getStateWithJustificationBits = func(bitfield.Bitvector4) (state.BeaconState, error) @@ -24,9 +22,7 @@ type getStateWithJustificationBits = func(bitfield.Bitvector4) (state.BeaconStat func VerifyBeaconStateJustificationBits(t *testing.T, factory getStateWithJustificationBits) { s, err := factory(bitfield.Bitvector4{1, 2, 3, 4}) require.NoError(t, err) - - bits := s.JustificationBits() - require.DeepEqual(t, bitfield.Bitvector4{1, 2, 3, 4}.Bytes(), bits.Bytes()) + require.DeepEqual(t, bitfield.Bitvector4{1, 2, 3, 4}.Bytes(), s.JustificationBits().Bytes()) } func VerifyBeaconStatePreviousJustifiedCheckpointNil(t *testing.T, factory getState) { diff --git a/beacon-chain/state/types/types.go b/beacon-chain/state/types/types.go index 6520498e51..9f225833f6 100644 --- a/beacon-chain/state/types/types.go +++ b/beacon-chain/state/types/types.go @@ -25,6 +25,14 @@ const ( CompressedArray ) +// BeaconStateField represents a field of the beacon state. +type BeaconStateField interface { + String(stateVersion int) string + RealPosition() int + ElemsInChunk() (uint64, error) + Native() bool +} + // String returns the name of the field index. func (f FieldIndex) String(stateVersion int) string { switch f { @@ -89,6 +97,12 @@ func (f FieldIndex) String(stateVersion int) string { } } +// RealPosition denotes the position of the field in the beacon state. +// The value might differ for different state versions. +func (f FieldIndex) RealPosition() int { + return int(f) +} + // ElemsInChunk returns the number of elements in the chunk (number of // elements that are able to be packed). func (f FieldIndex) ElemsInChunk() (uint64, error) { @@ -100,6 +114,10 @@ func (f FieldIndex) ElemsInChunk() (uint64, error) { } } +func (FieldIndex) Native() bool { + return false +} + // Below we define a set of useful enum values for the field // indices of the beacon state. For example, genesisTime is the // 0th field of the beacon state. This is helpful when we are diff --git a/beacon-chain/state/v1/BUILD.bazel b/beacon-chain/state/v1/BUILD.bazel index ce67fb3dbe..61a3337418 100644 --- a/beacon-chain/state/v1/BUILD.bazel +++ b/beacon-chain/state/v1/BUILD.bazel @@ -33,7 +33,7 @@ go_library( deps = [ "//beacon-chain/state:go_default_library", "//beacon-chain/state/fieldtrie:go_default_library", - "//beacon-chain/state/state-native/v1:go_default_library", + "//beacon-chain/state/state-native:go_default_library", "//beacon-chain/state/stateutil:go_default_library", "//beacon-chain/state/types:go_default_library", "//config/features:go_default_library", diff --git a/beacon-chain/state/v1/proofs.go b/beacon-chain/state/v1/proofs.go index d0981733ae..e8e3cba63a 100644 --- a/beacon-chain/state/v1/proofs.go +++ b/beacon-chain/state/v1/proofs.go @@ -48,7 +48,7 @@ func (b *BeaconState) FinalizedRootProof(ctx context.Context) ([][]byte, error) epochRoot := bytesutil.ToBytes32(epochBuf) proof := make([][]byte, 0) proof = append(proof, epochRoot[:]) - branch := fieldtrie.ProofFromMerkleLayers(b.merkleLayers, finalizedCheckpoint) + branch := fieldtrie.ProofFromMerkleLayers(b.merkleLayers, int(finalizedCheckpoint)) proof = append(proof, branch...) return proof, nil } diff --git a/beacon-chain/state/v1/state_trie.go b/beacon-chain/state/v1/state_trie.go index b4aea4618f..c0060c0a4b 100644 --- a/beacon-chain/state/v1/state_trie.go +++ b/beacon-chain/state/v1/state_trie.go @@ -8,7 +8,7 @@ import ( "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/beacon-chain/state" "github.com/prysmaticlabs/prysm/beacon-chain/state/fieldtrie" - statenative "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/v1" + statenative "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native" "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" "github.com/prysmaticlabs/prysm/beacon-chain/state/types" "github.com/prysmaticlabs/prysm/config/features" @@ -26,7 +26,7 @@ import ( // InitializeFromProto the beacon state from a protobuf representation. func InitializeFromProto(st *ethpb.BeaconState) (state.BeaconState, error) { if features.Get().EnableNativeState { - return statenative.InitializeFromProtoUnsafe(proto.Clone(st).(*ethpb.BeaconState)) + return statenative.InitializeFromProtoPhase0(proto.Clone(st).(*ethpb.BeaconState)) } return InitializeFromProtoUnsafe(proto.Clone(st).(*ethpb.BeaconState)) } @@ -35,7 +35,7 @@ func InitializeFromProto(st *ethpb.BeaconState) (state.BeaconState, error) { // and sets it as the inner state of the BeaconState type. func InitializeFromProtoUnsafe(st *ethpb.BeaconState) (state.BeaconState, error) { if features.Get().EnableNativeState { - return statenative.InitializeFromProtoUnsafe(st) + return statenative.InitializeFromProtoUnsafePhase0(st) } if st == nil { diff --git a/beacon-chain/state/v2/BUILD.bazel b/beacon-chain/state/v2/BUILD.bazel index 49a35ee355..5a6cf84b17 100644 --- a/beacon-chain/state/v2/BUILD.bazel +++ b/beacon-chain/state/v2/BUILD.bazel @@ -33,7 +33,7 @@ go_library( deps = [ "//beacon-chain/state:go_default_library", "//beacon-chain/state/fieldtrie:go_default_library", - "//beacon-chain/state/state-native/v2:go_default_library", + "//beacon-chain/state/state-native:go_default_library", "//beacon-chain/state/stateutil:go_default_library", "//beacon-chain/state/types:go_default_library", "//beacon-chain/state/v1:go_default_library", diff --git a/beacon-chain/state/v2/deprecated_setters_test.go b/beacon-chain/state/v2/deprecated_setters_test.go index 3ffe3e219c..c1fe140fec 100644 --- a/beacon-chain/state/v2/deprecated_setters_test.go +++ b/beacon-chain/state/v2/deprecated_setters_test.go @@ -10,11 +10,11 @@ import ( func TestBeaconState_AppendCurrentEpochAttestations(t *testing.T) { s, err := InitializeFromProtoUnsafe(ðpb.BeaconStateAltair{}) require.NoError(t, err) - require.ErrorContains(t, "AppendCurrentEpochAttestations is not supported for hard fork 1 beacon state", s.AppendCurrentEpochAttestations(nil)) + require.ErrorContains(t, "AppendCurrentEpochAttestations is not supported", s.AppendCurrentEpochAttestations(nil)) } func TestBeaconState_AppendPreviousEpochAttestations(t *testing.T) { s, err := InitializeFromProtoUnsafe(ðpb.BeaconStateAltair{}) require.NoError(t, err) - require.ErrorContains(t, "AppendPreviousEpochAttestations is not supported for hard fork 1 beacon state", s.AppendPreviousEpochAttestations(nil)) + require.ErrorContains(t, "AppendPreviousEpochAttestations is not supported", s.AppendPreviousEpochAttestations(nil)) } diff --git a/beacon-chain/state/v2/getters_test.go b/beacon-chain/state/v2/getters_test.go index 58804a4ea4..b70398aa84 100644 --- a/beacon-chain/state/v2/getters_test.go +++ b/beacon-chain/state/v2/getters_test.go @@ -59,6 +59,7 @@ func TestNilState_NoPanic(t *testing.T) { _, err = st.PreviousEpochParticipation() _ = err _ = st.JustificationBits() + _ = err _ = st.PreviousJustifiedCheckpoint() _ = st.CurrentJustifiedCheckpoint() _ = st.FinalizedCheckpoint() diff --git a/beacon-chain/state/v2/proofs.go b/beacon-chain/state/v2/proofs.go index e45ba49bcd..25ff918db3 100644 --- a/beacon-chain/state/v2/proofs.go +++ b/beacon-chain/state/v2/proofs.go @@ -41,7 +41,7 @@ func (b *BeaconState) CurrentSyncCommitteeProof(ctx context.Context) ([][]byte, if err := b.recomputeDirtyFields(ctx); err != nil { return nil, err } - return fieldtrie.ProofFromMerkleLayers(b.merkleLayers, currentSyncCommittee), nil + return fieldtrie.ProofFromMerkleLayers(b.merkleLayers, int(currentSyncCommittee)), nil } // NextSyncCommitteeProof from the state's Merkle trie representation. @@ -54,7 +54,7 @@ func (b *BeaconState) NextSyncCommitteeProof(ctx context.Context) ([][]byte, err if err := b.recomputeDirtyFields(ctx); err != nil { return nil, err } - return fieldtrie.ProofFromMerkleLayers(b.merkleLayers, nextSyncCommittee), nil + return fieldtrie.ProofFromMerkleLayers(b.merkleLayers, int(nextSyncCommittee)), nil } // FinalizedRootProof crafts a Merkle proof for the finalized root @@ -77,7 +77,7 @@ func (b *BeaconState) FinalizedRootProof(ctx context.Context) ([][]byte, error) epochRoot := bytesutil.ToBytes32(epochBuf) proof := make([][]byte, 0) proof = append(proof, epochRoot[:]) - branch := fieldtrie.ProofFromMerkleLayers(b.merkleLayers, finalizedCheckpoint) + branch := fieldtrie.ProofFromMerkleLayers(b.merkleLayers, int(finalizedCheckpoint)) proof = append(proof, branch...) return proof, nil } diff --git a/beacon-chain/state/v2/state_trie.go b/beacon-chain/state/v2/state_trie.go index a7ac3c5a06..de79d257ea 100644 --- a/beacon-chain/state/v2/state_trie.go +++ b/beacon-chain/state/v2/state_trie.go @@ -8,7 +8,7 @@ import ( "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/beacon-chain/state" "github.com/prysmaticlabs/prysm/beacon-chain/state/fieldtrie" - statenative "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/v2" + statenative "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native" "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" "github.com/prysmaticlabs/prysm/beacon-chain/state/types" "github.com/prysmaticlabs/prysm/config/features" @@ -26,7 +26,7 @@ import ( // InitializeFromProto the beacon state from a protobuf representation. func InitializeFromProto(st *ethpb.BeaconStateAltair) (state.BeaconStateAltair, error) { if features.Get().EnableNativeState { - return statenative.InitializeFromProtoUnsafe(proto.Clone(st).(*ethpb.BeaconStateAltair)) + return statenative.InitializeFromProtoAltair(proto.Clone(st).(*ethpb.BeaconStateAltair)) } return InitializeFromProtoUnsafe(proto.Clone(st).(*ethpb.BeaconStateAltair)) } @@ -35,7 +35,7 @@ func InitializeFromProto(st *ethpb.BeaconStateAltair) (state.BeaconStateAltair, // and sets it as the inner state of the BeaconState type. func InitializeFromProtoUnsafe(st *ethpb.BeaconStateAltair) (state.BeaconStateAltair, error) { if features.Get().EnableNativeState { - return statenative.InitializeFromProtoUnsafe(st) + return statenative.InitializeFromProtoUnsafeAltair(st) } if st == nil { diff --git a/beacon-chain/state/v3/BUILD.bazel b/beacon-chain/state/v3/BUILD.bazel index 2f33bf3120..c92c85f714 100644 --- a/beacon-chain/state/v3/BUILD.bazel +++ b/beacon-chain/state/v3/BUILD.bazel @@ -35,7 +35,7 @@ go_library( deps = [ "//beacon-chain/state:go_default_library", "//beacon-chain/state/fieldtrie:go_default_library", - "//beacon-chain/state/state-native/v3:go_default_library", + "//beacon-chain/state/state-native:go_default_library", "//beacon-chain/state/stateutil:go_default_library", "//beacon-chain/state/types:go_default_library", "//beacon-chain/state/v1:go_default_library", diff --git a/beacon-chain/state/v3/deprecated_setters.go b/beacon-chain/state/v3/deprecated_setters.go index da51300df5..8b07071cf9 100644 --- a/beacon-chain/state/v3/deprecated_setters.go +++ b/beacon-chain/state/v3/deprecated_setters.go @@ -7,7 +7,7 @@ import ( // AppendCurrentEpochAttestations is not supported for HF1 beacon state. func (*BeaconState) AppendCurrentEpochAttestations(_ *ethpb.PendingAttestation) error { - return errors.New("AppendCurrentEpochAttestations is not supported for version Bellatrix beacon state") + return errors.New("AppendCurrentEpochAttestations is not supported for Bellatrix beacon state") } // AppendPreviousEpochAttestations is not supported for HF1 beacon state. diff --git a/beacon-chain/state/v3/deprecated_setters_test.go b/beacon-chain/state/v3/deprecated_setters_test.go index 948b65112f..56c53c1e0a 100644 --- a/beacon-chain/state/v3/deprecated_setters_test.go +++ b/beacon-chain/state/v3/deprecated_setters_test.go @@ -10,11 +10,11 @@ import ( func TestBeaconState_AppendCurrentEpochAttestations(t *testing.T) { s, err := InitializeFromProtoUnsafe(ðpb.BeaconStateBellatrix{}) require.NoError(t, err) - require.ErrorContains(t, "AppendCurrentEpochAttestations is not supported for version Bellatrix beacon state", s.AppendCurrentEpochAttestations(nil)) + require.ErrorContains(t, "AppendCurrentEpochAttestations is not supported", s.AppendCurrentEpochAttestations(nil)) } func TestBeaconState_AppendPreviousEpochAttestations(t *testing.T) { s, err := InitializeFromProtoUnsafe(ðpb.BeaconStateBellatrix{}) require.NoError(t, err) - require.ErrorContains(t, "AppendPreviousEpochAttestations is not supported for version Bellatrix beacon state", s.AppendPreviousEpochAttestations(nil)) + require.ErrorContains(t, "AppendPreviousEpochAttestations is not supported", s.AppendPreviousEpochAttestations(nil)) } diff --git a/beacon-chain/state/v3/proofs.go b/beacon-chain/state/v3/proofs.go index c626914aa5..f397e3690d 100644 --- a/beacon-chain/state/v3/proofs.go +++ b/beacon-chain/state/v3/proofs.go @@ -41,7 +41,7 @@ func (b *BeaconState) CurrentSyncCommitteeProof(ctx context.Context) ([][]byte, if err := b.recomputeDirtyFields(ctx); err != nil { return nil, err } - return fieldtrie.ProofFromMerkleLayers(b.merkleLayers, currentSyncCommittee), nil + return fieldtrie.ProofFromMerkleLayers(b.merkleLayers, int(currentSyncCommittee)), nil } // NextSyncCommitteeProof from the state's Merkle trie representation. @@ -54,7 +54,7 @@ func (b *BeaconState) NextSyncCommitteeProof(ctx context.Context) ([][]byte, err if err := b.recomputeDirtyFields(ctx); err != nil { return nil, err } - return fieldtrie.ProofFromMerkleLayers(b.merkleLayers, nextSyncCommittee), nil + return fieldtrie.ProofFromMerkleLayers(b.merkleLayers, int(nextSyncCommittee)), nil } // FinalizedRootProof crafts a Merkle proof for the finalized root @@ -77,7 +77,7 @@ func (b *BeaconState) FinalizedRootProof(ctx context.Context) ([][]byte, error) epochRoot := bytesutil.ToBytes32(epochBuf) proof := make([][]byte, 0) proof = append(proof, epochRoot[:]) - branch := fieldtrie.ProofFromMerkleLayers(b.merkleLayers, finalizedCheckpoint) + branch := fieldtrie.ProofFromMerkleLayers(b.merkleLayers, int(finalizedCheckpoint)) proof = append(proof, branch...) return proof, nil } diff --git a/beacon-chain/state/v3/state_trie.go b/beacon-chain/state/v3/state_trie.go index 8e16d5eb9e..962e56910f 100644 --- a/beacon-chain/state/v3/state_trie.go +++ b/beacon-chain/state/v3/state_trie.go @@ -8,7 +8,7 @@ import ( "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/beacon-chain/state" "github.com/prysmaticlabs/prysm/beacon-chain/state/fieldtrie" - statenative "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/v3" + statenative "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native" "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" "github.com/prysmaticlabs/prysm/beacon-chain/state/types" "github.com/prysmaticlabs/prysm/config/features" @@ -26,7 +26,7 @@ import ( // InitializeFromProto the beacon state from a protobuf representation. func InitializeFromProto(st *ethpb.BeaconStateBellatrix) (state.BeaconStateBellatrix, error) { if features.Get().EnableNativeState { - return statenative.InitializeFromProto(proto.Clone(st).(*ethpb.BeaconStateBellatrix)) + return statenative.InitializeFromProtoBellatrix(proto.Clone(st).(*ethpb.BeaconStateBellatrix)) } return InitializeFromProtoUnsafe(proto.Clone(st).(*ethpb.BeaconStateBellatrix)) } @@ -35,7 +35,7 @@ func InitializeFromProto(st *ethpb.BeaconStateBellatrix) (state.BeaconStateBella // and sets it as the inner state of the BeaconState type. func InitializeFromProtoUnsafe(st *ethpb.BeaconStateBellatrix) (state.BeaconStateBellatrix, error) { if features.Get().EnableNativeState { - return statenative.InitializeFromProtoUnsafe(st) + return statenative.InitializeFromProtoUnsafeBellatrix(st) } if st == nil { diff --git a/config/features/flags.go b/config/features/flags.go index 869ac8472a..2bd65dbb0c 100644 --- a/config/features/flags.go +++ b/config/features/flags.go @@ -165,4 +165,5 @@ var E2EBeaconChainFlags = []string{ "--dev", "--use-check-point-cache", "--enable-active-balance-cache", + "--enable-native-state", } diff --git a/nogo_config.json b/nogo_config.json index 3c9d2b74b8..b4261401e0 100644 --- a/nogo_config.json +++ b/nogo_config.json @@ -147,11 +147,6 @@ "shared/.*": "", "slasher/.*": "", "validator/.*": "" - }, - "exclude_files": { - "beacon-chain/state/state-native/v1/generated.ssz.go": "Exclude generated SSZ file", - "beacon-chain/state/state-native/v2/generated.ssz.go": "Exclude generated SSZ file", - "beacon-chain/state/state-native/v3/generated.ssz.go": "Exclude generated SSZ file" } }, "properpermissions": { diff --git a/proto/migration/v1alpha1_to_v1.go b/proto/migration/v1alpha1_to_v1.go index 2efbfa0a9b..427eb871f5 100644 --- a/proto/migration/v1alpha1_to_v1.go +++ b/proto/migration/v1alpha1_to_v1.go @@ -367,6 +367,7 @@ func BeaconStateToProto(state state.BeaconState) (*ethpbv1.BeaconState, error) { if err != nil { return nil, errors.Wrapf(err, "could not get current epoch attestations from state") } + sourceJustificationBits := state.JustificationBits() sourcePrevJustifiedCheckpoint := state.PreviousJustifiedCheckpoint() sourceCurrJustifiedCheckpoint := state.CurrentJustifiedCheckpoint() sourceFinalizedCheckpoint := state.FinalizedCheckpoint() @@ -469,7 +470,7 @@ func BeaconStateToProto(state state.BeaconState) (*ethpbv1.BeaconState, error) { Slashings: state.Slashings(), PreviousEpochAttestations: resultPrevEpochAtts, CurrentEpochAttestations: resultCurrEpochAtts, - JustificationBits: bytesutil.SafeCopyBytes(state.JustificationBits()), + JustificationBits: bytesutil.SafeCopyBytes(sourceJustificationBits), PreviousJustifiedCheckpoint: ðpbv1.Checkpoint{ Epoch: sourcePrevJustifiedCheckpoint.Epoch, Root: bytesutil.SafeCopyBytes(sourcePrevJustifiedCheckpoint.Root), diff --git a/proto/migration/v1alpha1_to_v2.go b/proto/migration/v1alpha1_to_v2.go index c665e4cf8a..a681562363 100644 --- a/proto/migration/v1alpha1_to_v2.go +++ b/proto/migration/v1alpha1_to_v2.go @@ -257,6 +257,7 @@ func BeaconStateAltairToProto(altairState state.BeaconStateAltair) (*ethpbv2.Bea sourceEth1Data := altairState.Eth1Data() sourceEth1DataVotes := altairState.Eth1DataVotes() sourceValidators := altairState.Validators() + sourceJustificationBits := altairState.JustificationBits() sourcePrevJustifiedCheckpoint := altairState.PreviousJustifiedCheckpoint() sourceCurrJustifiedCheckpoint := altairState.CurrentJustifiedCheckpoint() sourceFinalizedCheckpoint := altairState.FinalizedCheckpoint() @@ -336,7 +337,7 @@ func BeaconStateAltairToProto(altairState state.BeaconStateAltair) (*ethpbv2.Bea Slashings: altairState.Slashings(), PreviousEpochParticipation: bytesutil.SafeCopyBytes(sourcePrevEpochParticipation), CurrentEpochParticipation: bytesutil.SafeCopyBytes(sourceCurrEpochParticipation), - JustificationBits: bytesutil.SafeCopyBytes(altairState.JustificationBits()), + JustificationBits: bytesutil.SafeCopyBytes(sourceJustificationBits), PreviousJustifiedCheckpoint: ðpbv1.Checkpoint{ Epoch: sourcePrevJustifiedCheckpoint.Epoch, Root: bytesutil.SafeCopyBytes(sourcePrevJustifiedCheckpoint.Root), @@ -370,6 +371,7 @@ func BeaconStateBellatrixToProto(st state.BeaconStateBellatrix) (*ethpbv2.Beacon sourceEth1Data := st.Eth1Data() sourceEth1DataVotes := st.Eth1DataVotes() sourceValidators := st.Validators() + sourceJustificationBits := st.JustificationBits() sourcePrevJustifiedCheckpoint := st.PreviousJustifiedCheckpoint() sourceCurrJustifiedCheckpoint := st.CurrentJustifiedCheckpoint() sourceFinalizedCheckpoint := st.FinalizedCheckpoint() @@ -453,7 +455,7 @@ func BeaconStateBellatrixToProto(st state.BeaconStateBellatrix) (*ethpbv2.Beacon Slashings: st.Slashings(), PreviousEpochParticipation: bytesutil.SafeCopyBytes(sourcePrevEpochParticipation), CurrentEpochParticipation: bytesutil.SafeCopyBytes(sourceCurrEpochParticipation), - JustificationBits: bytesutil.SafeCopyBytes(st.JustificationBits()), + JustificationBits: bytesutil.SafeCopyBytes(sourceJustificationBits), PreviousJustifiedCheckpoint: ðpbv1.Checkpoint{ Epoch: sourcePrevJustifiedCheckpoint.Epoch, Root: bytesutil.SafeCopyBytes(sourcePrevJustifiedCheckpoint.Root), diff --git a/runtime/interop/BUILD.bazel b/runtime/interop/BUILD.bazel index 3f631c6d16..8c4b93b152 100644 --- a/runtime/interop/BUILD.bazel +++ b/runtime/interop/BUILD.bazel @@ -12,7 +12,9 @@ go_library( "//async:go_default_library", "//beacon-chain/core/signing:go_default_library", "//beacon-chain/core/transition:go_default_library", + "//beacon-chain/state/state-native:go_default_library", "//beacon-chain/state/v1:go_default_library", + "//config/features:go_default_library", "//config/params:go_default_library", "//container/trie:go_default_library", "//crypto/bls:go_default_library", diff --git a/runtime/interop/generate_genesis_state.go b/runtime/interop/generate_genesis_state.go index ef2eaddea6..09721ceca4 100644 --- a/runtime/interop/generate_genesis_state.go +++ b/runtime/interop/generate_genesis_state.go @@ -10,7 +10,9 @@ import ( "github.com/prysmaticlabs/prysm/async" "github.com/prysmaticlabs/prysm/beacon-chain/core/signing" coreState "github.com/prysmaticlabs/prysm/beacon-chain/core/transition" + state_native "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native" v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" + "github.com/prysmaticlabs/prysm/config/features" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/container/trie" "github.com/prysmaticlabs/prysm/crypto/bls" @@ -65,7 +67,12 @@ func GenerateGenesisStateFromDepositData( return nil, nil, errors.Wrap(err, "could not generate genesis state") } - pbState, err := v1.ProtobufBeaconState(beaconState.CloneInnerState()) + var pbState *ethpb.BeaconState + if features.Get().EnableNativeState { + pbState, err = state_native.ProtobufBeaconStatePhase0(beaconState.InnerStateUnsafe()) + } else { + pbState, err = v1.ProtobufBeaconState(beaconState.InnerStateUnsafe()) + } if err != nil { return nil, nil, err } diff --git a/testing/endtoend/components/beacon_node.go b/testing/endtoend/components/beacon_node.go index b24d355892..eebfa386c2 100644 --- a/testing/endtoend/components/beacon_node.go +++ b/testing/endtoend/components/beacon_node.go @@ -148,7 +148,9 @@ func (node *BeaconNode) Start(ctx context.Context) error { args = append(args, "--pprof", fmt.Sprintf("--pprofport=%d", e2e.TestParams.Ports.PrysmBeaconNodePprofPort+index)) } // Only add in the feature flags if we either aren't performing a control test - // on our features or the beacon index is a power of 2. + // on our features or the beacon index is a multiplier of 2 (idea is to split nodes + // equally down the line with one group having feature flags and the other without + // feature flags; this is to allow A-B testing on new features) if !config.TestFeature || index%2 == 0 { args = append(args, features.E2EBeaconChainFlags...) } diff --git a/testing/util/state.go b/testing/util/state.go index 1d97c51706..91d1ab8f48 100644 --- a/testing/util/state.go +++ b/testing/util/state.go @@ -23,7 +23,7 @@ import ( // It fills state and block roots with hex representations of natural numbers starting with 0. // Example: 16 becomes 0x00...0f. func FillRootsNaturalOpt(state *ethpb.BeaconState) error { - roots, err := prepareRoots() + roots, err := PrepareRoots(int(params.BeaconConfig().SlotsPerHistoricalRoot)) if err != nil { return err } @@ -36,7 +36,7 @@ func FillRootsNaturalOpt(state *ethpb.BeaconState) error { // It fills state and block roots with hex representations of natural numbers starting with 0. // Example: 16 becomes 0x00...0f. func FillRootsNaturalOptAltair(state *ethpb.BeaconStateAltair) error { - roots, err := prepareRoots() + roots, err := PrepareRoots(int(params.BeaconConfig().SlotsPerHistoricalRoot)) if err != nil { return err } @@ -49,7 +49,7 @@ func FillRootsNaturalOptAltair(state *ethpb.BeaconStateAltair) error { // It fills state and block roots with hex representations of natural numbers starting with 0. // Example: 16 becomes 0x00...0f. func FillRootsNaturalOptBellatrix(state *ethpb.BeaconStateBellatrix) error { - roots, err := prepareRoots() + roots, err := PrepareRoots(int(params.BeaconConfig().SlotsPerHistoricalRoot)) if err != nil { return err } @@ -250,10 +250,11 @@ func filledByteSlice2D(length, innerLen uint64) [][]byte { return b } -func prepareRoots() ([][]byte, error) { - rootsLen := params.MainnetConfig().SlotsPerHistoricalRoot - roots := make([][]byte, rootsLen) - for i := types.Slot(0); i < rootsLen; i++ { +// PrepareRoots returns a list of roots with hex representations of natural numbers starting with 0. +// Example: 16 becomes 0x00...0f. +func PrepareRoots(size int) ([][]byte, error) { + roots := make([][]byte, size) + for i := 0; i < size; i++ { roots[i] = make([]byte, fieldparams.RootLength) } for j := 0; j < len(roots); j++ { diff --git a/tools/exploredb/main.go b/tools/exploredb/main.go index 212d0c5886..810c3cd02c 100644 --- a/tools/exploredb/main.go +++ b/tools/exploredb/main.go @@ -352,7 +352,8 @@ func printStates(stateC <-chan *modifiedState, doneC chan<- bool) { log.Infof("previous_epoch_attestations : sizeSSZ = %s, count = %d", humanize.Bytes(size), count) size, count = sizeAndCountGeneric(st.CurrentEpochAttestations()) log.Infof("current_epoch_attestations : sizeSSZ = %s, count = %d", humanize.Bytes(size), count) - log.Infof("justification_bits : size = %s, count = %d", humanize.Bytes(st.JustificationBits().Len()), st.JustificationBits().Count()) + justificationBits := st.JustificationBits() + log.Infof("justification_bits : size = %s, count = %d", humanize.Bytes(justificationBits.Len()), justificationBits.Count()) log.Infof("previous_justified_checkpoint : sizeSSZ = %s", humanize.Bytes(uint64(st.PreviousJustifiedCheckpoint().SizeSSZ()))) log.Infof("current_justified_checkpoint : sizeSSZ = %s", humanize.Bytes(uint64(st.CurrentJustifiedCheckpoint().SizeSSZ()))) log.Infof("finalized_checkpoint : sizeSSZ = %s", humanize.Bytes(uint64(st.FinalizedCheckpoint().SizeSSZ())))