From 6406afc6cfcadcbb74dd112d8081f568cfe70afb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rados=C5=82aw=20Kapka?= Date: Tue, 1 Feb 2022 01:32:39 +0100 Subject: [PATCH] Native beacon state: v3 (#10139) * Native beacon state: v3 * nogo_config * remove duplicated bazel rule * gzl * fix unnecessary assignment * review Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com> Co-authored-by: Raul Jordan --- .../state/state-native/v3/BUILD.bazel | 34 +- .../state-native/v3/beacon_state_mainnet.go | 54 ++ .../v3/beacon_state_mainnet_test.go | 86 +++ .../state-native/v3/beacon_state_minimal.go | 54 ++ .../v3/beacon_state_minimal_test.go | 86 +++ .../state/state-native/v3/generated.ssz.go | 539 ++++++++++++++++++ .../state/state-native/v3/getters_block.go | 71 +-- .../state-native/v3/getters_block_test.go | 30 +- .../state-native/v3/getters_checkpoint.go | 96 +--- .../state/state-native/v3/getters_eth1.go | 55 +- .../state/state-native/v3/getters_misc.go | 155 +---- .../state-native/v3/getters_participation.go | 36 +- .../state-native/v3/getters_payload_header.go | 17 +- .../state/state-native/v3/getters_randao.go | 50 +- .../state/state-native/v3/getters_state.go | 163 +++--- .../state-native/v3/getters_sync_committee.go | 36 +- .../state/state-native/v3/getters_test.go | 61 -- .../state-native/v3/getters_validator.go | 144 ++--- beacon-chain/state/state-native/v3/proofs.go | 2 +- .../state/state-native/v3/proofs_test.go | 2 +- .../state/state-native/v3/setters_block.go | 33 +- .../state-native/v3/setters_checkpoint.go | 20 +- .../state/state-native/v3/setters_eth1.go | 28 +- .../state/state-native/v3/setters_misc.go | 39 +- .../state-native/v3/setters_participation.go | 36 +- .../state-native/v3/setters_payload_header.go | 5 +- .../state/state-native/v3/setters_randao.go | 29 +- .../state/state-native/v3/setters_state.go | 29 +- .../state-native/v3/setters_sync_committee.go | 10 +- .../state/state-native/v3/setters_test.go | 96 +--- .../state-native/v3/setters_validator.go | 89 +-- .../state/state-native/v3/state_trie.go | 192 ++++--- .../state/state-native/v3/state_trie_test.go | 6 +- beacon-chain/state/state-native/v3/types.go | 24 - nogo_config.json | 3 +- 35 files changed, 1405 insertions(+), 1005 deletions(-) create mode 100644 beacon-chain/state/state-native/v3/beacon_state_mainnet.go create mode 100644 beacon-chain/state/state-native/v3/beacon_state_mainnet_test.go create mode 100644 beacon-chain/state/state-native/v3/beacon_state_minimal.go create mode 100644 beacon-chain/state/state-native/v3/beacon_state_minimal_test.go create mode 100644 beacon-chain/state/state-native/v3/generated.ssz.go diff --git a/beacon-chain/state/state-native/v3/BUILD.bazel b/beacon-chain/state/state-native/v3/BUILD.bazel index 1c8b01565..84c4bd823 100644 --- a/beacon-chain/state/state-native/v3/BUILD.bazel +++ b/beacon-chain/state/state-native/v3/BUILD.bazel @@ -1,4 +1,6 @@ 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", @@ -29,7 +31,11 @@ go_library( "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__", @@ -38,6 +44,7 @@ go_library( ], deps = [ "//beacon-chain/state:go_default_library", + "//beacon-chain/state/state-native/custom-types:go_default_library", "//beacon-chain/state/state-native/fieldtrie:go_default_library", "//beacon-chain/state/state-native/v1:go_default_library", "//beacon-chain/state/stateutil:go_default_library", @@ -51,6 +58,7 @@ 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_eth2_types//:go_default_library", "@com_github_prysmaticlabs_go_bitfield//:go_default_library", @@ -70,13 +78,16 @@ go_test( "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/state-native/v1:go_default_library", "//beacon-chain/state/stateutil:go_default_library", - "//beacon-chain/state/types:go_default_library", + "//beacon-chain/state/v3:go_default_library", "//config/features:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", @@ -91,3 +102,20 @@ go_test( "@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", + "//proto/prysm/v1alpha1:go_default_library", + "@com_github_prysmaticlabs_eth2_types//: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/v3/beacon_state_mainnet.go new file mode 100644 index 000000000..3688ebdb3 --- /dev/null +++ b/beacon-chain/state/state-native/v3/beacon_state_mainnet.go @@ -0,0 +1,54 @@ +// +build !minimal + +package v3 + +import ( + "sync" + + eth2types "github.com/prysmaticlabs/eth2-types" + "github.com/prysmaticlabs/go-bitfield" + customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types" + "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/fieldtrie" + "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" + "github.com/prysmaticlabs/prysm/beacon-chain/state/types" + 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"` + 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 + valMapHandler *stateutil.ValidatorMapHandler + merkleLayers [][][]byte + sharedFieldReferences map[types.FieldIndex]*stateutil.Reference +} 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 new file mode 100644 index 000000000..078271101 --- /dev/null +++ b/beacon-chain/state/state-native/v3/beacon_state_mainnet_test.go @@ -0,0 +1,86 @@ +// +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.go b/beacon-chain/state/state-native/v3/beacon_state_minimal.go new file mode 100644 index 000000000..9a29ece79 --- /dev/null +++ b/beacon-chain/state/state-native/v3/beacon_state_minimal.go @@ -0,0 +1,54 @@ +// +build minimal + +package v3 + +import ( + "sync" + + eth2types "github.com/prysmaticlabs/eth2-types" + "github.com/prysmaticlabs/go-bitfield" + customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types" + "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/fieldtrie" + "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" + "github.com/prysmaticlabs/prysm/beacon-chain/state/types" + 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"` + 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 + valMapHandler *stateutil.ValidatorMapHandler + merkleLayers [][][]byte + sharedFieldReferences map[types.FieldIndex]*stateutil.Reference +} 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 new file mode 100644 index 000000000..f5edba5ee --- /dev/null +++ b/beacon-chain/state/state-native/v3/beacon_state_minimal_test.go @@ -0,0 +1,86 @@ +// +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/generated.ssz.go b/beacon-chain/state/state-native/v3/generated.ssz.go new file mode 100644 index 000000000..d5462a668 --- /dev/null +++ b/beacon-chain/state/state-native/v3/generated.ssz.go @@ -0,0 +1,539 @@ +// Code generated by fastssz. DO NOT EDIT. +// Hash: a71c6e70ae416774612961057f4c96b97b5c3323270a80167d30ea672ea2f5cd +package v3 + +import ( + ssz "github.com/ferranbt/fastssz" + eth2types "github.com/prysmaticlabs/eth2-types" + 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 index b9f4bb5b3..403343036 100644 --- a/beacon-chain/state/state-native/v3/getters_block.go +++ b/beacon-chain/state/state-native/v3/getters_block.go @@ -1,47 +1,42 @@ package v3 import ( - "github.com/prysmaticlabs/prysm/encoding/bytesutil" + "fmt" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ) // LatestBlockHeader stored within the beacon state. func (b *BeaconState) LatestBlockHeader() *ethpb.BeaconBlockHeader { - if !b.hasInnerState() { - return nil - } - if b.state.LatestBlockHeader == nil { + if b.latestBlockHeader == nil { return nil } b.lock.RLock() defer b.lock.RUnlock() - return b.latestBlockHeader() + return b.latestBlockHeaderVal() } -// latestBlockHeader stored within the beacon state. +// latestBlockHeaderVal stored within the beacon state. // This assumes that a lock is already held on BeaconState. -func (b *BeaconState) latestBlockHeader() *ethpb.BeaconBlockHeader { - if !b.hasInnerState() { - return nil - } - if b.state.LatestBlockHeader == nil { +func (b *BeaconState) latestBlockHeaderVal() *ethpb.BeaconBlockHeader { + if b.latestBlockHeader == nil { return nil } hdr := ðpb.BeaconBlockHeader{ - Slot: b.state.LatestBlockHeader.Slot, - ProposerIndex: b.state.LatestBlockHeader.ProposerIndex, + Slot: b.latestBlockHeader.Slot, + ProposerIndex: b.latestBlockHeader.ProposerIndex, } - parentRoot := make([]byte, len(b.state.LatestBlockHeader.ParentRoot)) - bodyRoot := make([]byte, len(b.state.LatestBlockHeader.BodyRoot)) - stateRoot := make([]byte, len(b.state.LatestBlockHeader.StateRoot)) + parentRoot := make([]byte, len(b.latestBlockHeader.ParentRoot)) + bodyRoot := make([]byte, len(b.latestBlockHeader.BodyRoot)) + stateRoot := make([]byte, len(b.latestBlockHeader.StateRoot)) - copy(parentRoot, b.state.LatestBlockHeader.ParentRoot) - copy(bodyRoot, b.state.LatestBlockHeader.BodyRoot) - copy(stateRoot, b.state.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 @@ -50,50 +45,40 @@ func (b *BeaconState) latestBlockHeader() *ethpb.BeaconBlockHeader { // BlockRoots kept track of in the beacon state. func (b *BeaconState) BlockRoots() [][]byte { - if !b.hasInnerState() { - return nil - } - if b.state.BlockRoots == nil { + if b.blockRoots == nil { return nil } b.lock.RLock() defer b.lock.RUnlock() - return b.blockRoots() -} - -// blockRoots kept track of in the beacon state. -// This assumes that a lock is already held on BeaconState. -func (b *BeaconState) blockRoots() [][]byte { - if !b.hasInnerState() { - return nil - } - return bytesutil.SafeCopy2dBytes(b.state.BlockRoots) + 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.hasInnerState() { - return nil, ErrNilInnerState - } - if b.state.BlockRoots == nil { + if b.blockRoots == nil { return nil, nil } b.lock.RLock() defer b.lock.RUnlock() - return b.blockRootAtIndex(idx) + 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) ([]byte, error) { - if !b.hasInnerState() { - return nil, ErrNilInnerState +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 bytesutil.SafeCopyRootAtIndex(b.state.BlockRoots, 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 index 1e328ee30..7c6fc9acc 100644 --- a/beacon-chain/state/state-native/v3/getters_block_test.go +++ b/beacon-chain/state/state-native/v3/getters_block_test.go @@ -3,6 +3,7 @@ package v3 import ( "testing" + fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/testing/require" @@ -29,9 +30,21 @@ func TestBeaconState_BlockRoots(t *testing.T) { s, err := InitializeFromProto(ðpb.BeaconStateBellatrix{}) require.NoError(t, err) got := s.BlockRoots() - require.DeepEqual(t, ([][]byte)(nil), got) + want := make([][]byte, fieldparams.BlockRootsLength) + for i := range want { + want[i] = make([]byte, fieldparams.RootLength) + } + require.DeepEqual(t, want, got) - want := [][]byte{{'a'}} + want = make([][]byte, fieldparams.BlockRootsLength) + for i := range want { + if i == 0 { + want[i] = bytesutil.PadTo([]byte{'a'}, fieldparams.RootLength) + } else { + want[i] = make([]byte, fieldparams.RootLength) + } + + } s, err = InitializeFromProto(ðpb.BeaconStateBellatrix{BlockRoots: want}) require.NoError(t, err) got = s.BlockRoots() @@ -47,13 +60,18 @@ func TestBeaconState_BlockRootAtIndex(t *testing.T) { require.NoError(t, err) got, err := s.BlockRootAtIndex(0) require.NoError(t, err) - require.DeepEqual(t, ([]byte)(nil), got) + require.DeepEqual(t, bytesutil.PadTo([]byte{}, fieldparams.RootLength), got) - r := [][]byte{{'a'}} - s, err = InitializeFromProto(ðpb.BeaconStateBellatrix{BlockRoots: r}) + r := [fieldparams.BlockRootsLength][fieldparams.RootLength]byte{{'a'}} + bRoots := make([][]byte, len(r)) + for i, root := range r { + tmp := root + bRoots[i] = tmp[:] + } + s, err = InitializeFromProto(ðpb.BeaconStateBellatrix{BlockRoots: bRoots}) require.NoError(t, err) got, err = s.BlockRootAtIndex(0) require.NoError(t, err) - want := bytesutil.PadTo([]byte{'a'}, 32) + want := bytesutil.PadTo([]byte{'a'}, fieldparams.RootLength) require.DeepSSZEqual(t, want, got) } diff --git a/beacon-chain/state/state-native/v3/getters_checkpoint.go b/beacon-chain/state/state-native/v3/getters_checkpoint.go index f6b6eab16..a52e5feb2 100644 --- a/beacon-chain/state/state-native/v3/getters_checkpoint.go +++ b/beacon-chain/state/state-native/v3/getters_checkpoint.go @@ -10,151 +10,115 @@ import ( // JustificationBits marking which epochs have been justified in the beacon chain. func (b *BeaconState) JustificationBits() bitfield.Bitvector4 { - if !b.hasInnerState() { - return nil - } - if b.state.JustificationBits == nil { + if b.justificationBits == nil { return nil } b.lock.RLock() defer b.lock.RUnlock() - return b.justificationBits() + return b.justificationBitsVal() } -// justificationBits marking which epochs have been justified in the beacon chain. +// justificationBitsVal marking which epochs have been justified in the beacon chain. // This assumes that a lock is already held on BeaconState. -func (b *BeaconState) justificationBits() bitfield.Bitvector4 { - if !b.hasInnerState() { - return nil - } - if b.state.JustificationBits == nil { +func (b *BeaconState) justificationBitsVal() bitfield.Bitvector4 { + if b.justificationBits == nil { return nil } - res := make([]byte, len(b.state.JustificationBits.Bytes())) - copy(res, b.state.JustificationBits.Bytes()) + 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.hasInnerState() { - return nil - } - if b.state.PreviousJustifiedCheckpoint == nil { + if b.previousJustifiedCheckpoint == nil { return nil } b.lock.RLock() defer b.lock.RUnlock() - return b.previousJustifiedCheckpoint() + return b.previousJustifiedCheckpointVal() } -// previousJustifiedCheckpoint denoting an epoch and block root. +// previousJustifiedCheckpointVal denoting an epoch and block root. // This assumes that a lock is already held on BeaconState. -func (b *BeaconState) previousJustifiedCheckpoint() *ethpb.Checkpoint { - if !b.hasInnerState() { - return nil - } - - return ethpb.CopyCheckpoint(b.state.PreviousJustifiedCheckpoint) +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.hasInnerState() { - return nil - } - if b.state.CurrentJustifiedCheckpoint == nil { + if b.currentJustifiedCheckpoint == nil { return nil } b.lock.RLock() defer b.lock.RUnlock() - return b.currentJustifiedCheckpoint() + return b.currentJustifiedCheckpointVal() } -// currentJustifiedCheckpoint denoting an epoch and block root. +// currentJustifiedCheckpointVal denoting an epoch and block root. // This assumes that a lock is already held on BeaconState. -func (b *BeaconState) currentJustifiedCheckpoint() *ethpb.Checkpoint { - if !b.hasInnerState() { - return nil - } - - return ethpb.CopyCheckpoint(b.state.CurrentJustifiedCheckpoint) +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.hasInnerState() { - return false - } - if b.state.CurrentJustifiedCheckpoint == nil { + if b.currentJustifiedCheckpoint == nil { return false } - if c.Epoch != b.state.CurrentJustifiedCheckpoint.Epoch { + if c.Epoch != b.currentJustifiedCheckpoint.Epoch { return false } - return bytes.Equal(c.Root, b.state.CurrentJustifiedCheckpoint.Root) + 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.hasInnerState() { - return false - } - if b.state.PreviousJustifiedCheckpoint == nil { + if b.previousJustifiedCheckpoint == nil { return false } - if c.Epoch != b.state.PreviousJustifiedCheckpoint.Epoch { + if c.Epoch != b.previousJustifiedCheckpoint.Epoch { return false } - return bytes.Equal(c.Root, b.state.PreviousJustifiedCheckpoint.Root) + return bytes.Equal(c.Root, b.previousJustifiedCheckpoint.Root) } // FinalizedCheckpoint denoting an epoch and block root. func (b *BeaconState) FinalizedCheckpoint() *ethpb.Checkpoint { - if !b.hasInnerState() { - return nil - } - if b.state.FinalizedCheckpoint == nil { + if b.finalizedCheckpoint == nil { return nil } b.lock.RLock() defer b.lock.RUnlock() - return b.finalizedCheckpoint() + return b.finalizedCheckpointVal() } -// finalizedCheckpoint denoting an epoch and block root. +// finalizedCheckpointVal denoting an epoch and block root. // This assumes that a lock is already held on BeaconState. -func (b *BeaconState) finalizedCheckpoint() *ethpb.Checkpoint { - if !b.hasInnerState() { - return nil - } - - return ethpb.CopyCheckpoint(b.state.FinalizedCheckpoint) +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.hasInnerState() { - return 0 - } - if b.state.FinalizedCheckpoint == nil { + if b.finalizedCheckpoint == nil { return 0 } b.lock.RLock() defer b.lock.RUnlock() - return b.state.FinalizedCheckpoint.Epoch + return b.finalizedCheckpoint.Epoch } diff --git a/beacon-chain/state/state-native/v3/getters_eth1.go b/beacon-chain/state/state-native/v3/getters_eth1.go index 04449eb9d..55096f293 100644 --- a/beacon-chain/state/state-native/v3/getters_eth1.go +++ b/beacon-chain/state/state-native/v3/getters_eth1.go @@ -6,62 +6,50 @@ import ( // Eth1Data corresponding to the proof-of-work chain information stored in the beacon state. func (b *BeaconState) Eth1Data() *ethpb.Eth1Data { - if !b.hasInnerState() { - return nil - } - if b.state.Eth1Data == nil { + if b.eth1Data == nil { return nil } b.lock.RLock() defer b.lock.RUnlock() - return b.eth1Data() + return b.eth1DataVal() } -// eth1Data corresponding to the proof-of-work chain information stored in the beacon state. +// 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) eth1Data() *ethpb.Eth1Data { - if !b.hasInnerState() { - return nil - } - if b.state.Eth1Data == nil { +func (b *BeaconState) eth1DataVal() *ethpb.Eth1Data { + if b.eth1Data == nil { return nil } - return ethpb.CopyETH1Data(b.state.Eth1Data) + 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.hasInnerState() { - return nil - } - if b.state.Eth1DataVotes == nil { + if b.eth1DataVotes == nil { return nil } b.lock.RLock() defer b.lock.RUnlock() - return b.eth1DataVotes() + return b.eth1DataVotesVal() } -// eth1DataVotes corresponds to votes from Ethereum on the canonical proof-of-work chain +// 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) eth1DataVotes() []*ethpb.Eth1Data { - if !b.hasInnerState() { - return nil - } - if b.state.Eth1DataVotes == nil { +func (b *BeaconState) eth1DataVotesVal() []*ethpb.Eth1Data { + if b.eth1DataVotes == nil { return nil } - res := make([]*ethpb.Eth1Data, len(b.state.Eth1DataVotes)) + res := make([]*ethpb.Eth1Data, len(b.eth1DataVotes)) for i := 0; i < len(res); i++ { - res[i] = ethpb.CopyETH1Data(b.state.Eth1DataVotes[i]) + res[i] = ethpb.CopyETH1Data(b.eth1DataVotes[i]) } return res } @@ -69,23 +57,8 @@ func (b *BeaconState) eth1DataVotes() []*ethpb.Eth1Data { // 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 { - if !b.hasInnerState() { - return 0 - } - b.lock.RLock() defer b.lock.RUnlock() - return b.eth1DepositIndex() -} - -// eth1DepositIndex corresponds to the index of the deposit made to the -// validator deposit contract at the time of this state's eth1 data. -// This assumes that a lock is already held on BeaconState. -func (b *BeaconState) eth1DepositIndex() uint64 { - if !b.hasInnerState() { - return 0 - } - - return b.state.Eth1DepositIndex + return b.eth1DepositIndex } diff --git a/beacon-chain/state/state-native/v3/getters_misc.go b/beacon-chain/state/state-native/v3/getters_misc.go index e84d682d0..42b964a05 100644 --- a/beacon-chain/state/state-native/v3/getters_misc.go +++ b/beacon-chain/state/state-native/v3/getters_misc.go @@ -1,111 +1,25 @@ package v3 import ( - "time" - types "github.com/prysmaticlabs/eth2-types" - "github.com/prysmaticlabs/prysm/config/params" - "github.com/prysmaticlabs/prysm/encoding/bytesutil" 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 { - if !b.hasInnerState() { - return 0 - } - b.lock.RLock() defer b.lock.RUnlock() - return b.genesisTime() -} - -// genesisTime of the beacon state as a uint64. -// This assumes that a lock is already held on BeaconState. -func (b *BeaconState) genesisTime() uint64 { - if !b.hasInnerState() { - return 0 - } - - return b.state.GenesisTime + return b.genesisTime } // GenesisValidatorRoot of the beacon state. func (b *BeaconState) GenesisValidatorRoot() []byte { - if !b.hasInnerState() { - return nil - } - if b.state.GenesisValidatorsRoot == nil { - return params.BeaconConfig().ZeroHash[:] - } - b.lock.RLock() defer b.lock.RUnlock() - return b.genesisValidatorRoot() -} - -// genesisValidatorRoot of the beacon state. -// This assumes that a lock is already held on BeaconState. -func (b *BeaconState) genesisValidatorRoot() []byte { - if !b.hasInnerState() { - return nil - } - if b.state.GenesisValidatorsRoot == nil { - return params.BeaconConfig().ZeroHash[:] - } - - root := make([]byte, 32) - copy(root, b.state.GenesisValidatorsRoot) - return root -} - -// GenesisUnixTime returns the genesis time as time.Time. -func (b *BeaconState) GenesisUnixTime() time.Time { - if !b.hasInnerState() { - return time.Unix(0, 0) - } - - b.lock.RLock() - defer b.lock.RUnlock() - - return b.genesisUnixTime() -} - -// genesisUnixTime returns the genesis time as time.Time. -// This assumes that a lock is already held on BeaconState. -func (b *BeaconState) genesisUnixTime() time.Time { - if !b.hasInnerState() { - return time.Unix(0, 0) - } - - return time.Unix(int64(b.state.GenesisTime), 0) -} - -// ParentRoot is a convenience method to access state.LatestBlockRoot.ParentRoot. -func (b *BeaconState) ParentRoot() [32]byte { - if !b.hasInnerState() { - return [32]byte{} - } - - b.lock.RLock() - defer b.lock.RUnlock() - - return b.parentRoot() -} - -// parentRoot is a convenience method to access state.LatestBlockRoot.ParentRoot. -// This assumes that a lock is already held on BeaconState. -func (b *BeaconState) parentRoot() [32]byte { - if !b.hasInnerState() { - return [32]byte{} - } - - parentRoot := [32]byte{} - copy(parentRoot[:], b.state.LatestBlockHeader.ParentRoot) - return parentRoot + return b.genesisValidatorsRoot[:] } // Version of the beacon state. This method @@ -117,95 +31,60 @@ func (_ *BeaconState) Version() int { // Slot of the current beacon chain state. func (b *BeaconState) Slot() types.Slot { - if !b.hasInnerState() { - return 0 - } - b.lock.RLock() defer b.lock.RUnlock() - return b.slot() -} - -// slot of the current beacon chain state. -// This assumes that a lock is already held on BeaconState. -func (b *BeaconState) slot() types.Slot { - if !b.hasInnerState() { - return 0 - } - - return b.state.Slot + return b.slot } // Fork version of the beacon chain. func (b *BeaconState) Fork() *ethpb.Fork { - if !b.hasInnerState() { - return nil - } - if b.state.Fork == nil { + if b.fork == nil { return nil } b.lock.RLock() defer b.lock.RUnlock() - return b.fork() + return b.forkVal() } -// fork version of the beacon chain. +// forkVal version of the beacon chain. // This assumes that a lock is already held on BeaconState. -func (b *BeaconState) fork() *ethpb.Fork { - if !b.hasInnerState() { - return nil - } - if b.state.Fork == nil { +func (b *BeaconState) forkVal() *ethpb.Fork { + if b.fork == nil { return nil } - prevVersion := make([]byte, len(b.state.Fork.PreviousVersion)) - copy(prevVersion, b.state.Fork.PreviousVersion) - currVersion := make([]byte, len(b.state.Fork.CurrentVersion)) - copy(currVersion, b.state.Fork.CurrentVersion) + 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.state.Fork.Epoch, + Epoch: b.fork.Epoch, } } // HistoricalRoots based on epochs stored in the beacon state. func (b *BeaconState) HistoricalRoots() [][]byte { - if !b.hasInnerState() { - return nil - } - if b.state.HistoricalRoots == nil { + if b.historicalRoots == nil { return nil } b.lock.RLock() defer b.lock.RUnlock() - return b.historicalRoots() -} - -// historicalRoots based on epochs stored in the beacon state. -// This assumes that a lock is already held on BeaconState. -func (b *BeaconState) historicalRoots() [][]byte { - if !b.hasInnerState() { - return nil - } - return bytesutil.SafeCopy2dBytes(b.state.HistoricalRoots) + 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.hasInnerState() { - return 0 - } - if b.state.Balances == nil { + if b.balances == nil { return 0 } - return len(b.state.Balances) + return len(b.balances) } diff --git a/beacon-chain/state/state-native/v3/getters_participation.go b/beacon-chain/state/state-native/v3/getters_participation.go index 42358b01d..10fb7073e 100644 --- a/beacon-chain/state/state-native/v3/getters_participation.go +++ b/beacon-chain/state/state-native/v3/getters_participation.go @@ -2,52 +2,40 @@ package v3 // CurrentEpochParticipation corresponding to participation bits on the beacon chain. func (b *BeaconState) CurrentEpochParticipation() ([]byte, error) { - if !b.hasInnerState() { - return nil, nil - } - if b.state.CurrentEpochParticipation == nil { + if b.currentEpochParticipation == nil { return nil, nil } b.lock.RLock() defer b.lock.RUnlock() - return b.currentEpochParticipation(), nil + return b.currentEpochParticipationVal(), nil } // PreviousEpochParticipation corresponding to participation bits on the beacon chain. func (b *BeaconState) PreviousEpochParticipation() ([]byte, error) { - if !b.hasInnerState() { - return nil, nil - } - if b.state.PreviousEpochParticipation == nil { + if b.previousEpochParticipation == nil { return nil, nil } b.lock.RLock() defer b.lock.RUnlock() - return b.previousEpochParticipation(), nil + return b.previousEpochParticipationVal(), nil } -// currentEpochParticipation corresponding to participation bits on the beacon chain. +// currentEpochParticipationVal corresponding to participation bits on the beacon chain. // This assumes that a lock is already held on BeaconState. -func (b *BeaconState) currentEpochParticipation() []byte { - if !b.hasInnerState() { - return nil - } - tmp := make([]byte, len(b.state.CurrentEpochParticipation)) - copy(tmp, b.state.CurrentEpochParticipation) +func (b *BeaconState) currentEpochParticipationVal() []byte { + tmp := make([]byte, len(b.currentEpochParticipation)) + copy(tmp, b.currentEpochParticipation) return tmp } -// previousEpochParticipation corresponding to participation bits on the beacon chain. +// previousEpochParticipationVal corresponding to participation bits on the beacon chain. // This assumes that a lock is already held on BeaconState. -func (b *BeaconState) previousEpochParticipation() []byte { - if !b.hasInnerState() { - return nil - } - tmp := make([]byte, len(b.state.PreviousEpochParticipation)) - copy(tmp, b.state.PreviousEpochParticipation) +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/v3/getters_payload_header.go b/beacon-chain/state/state-native/v3/getters_payload_header.go index bfbd893f2..26251733e 100644 --- a/beacon-chain/state/state-native/v3/getters_payload_header.go +++ b/beacon-chain/state/state-native/v3/getters_payload_header.go @@ -6,25 +6,18 @@ import ( // LatestExecutionPayloadHeader of the beacon state. func (b *BeaconState) LatestExecutionPayloadHeader() (*ethpb.ExecutionPayloadHeader, error) { - if !b.hasInnerState() { - return nil, nil - } - if b.state.LatestExecutionPayloadHeader == nil { + if b.latestExecutionPayloadHeader == nil { return nil, nil } b.lock.RLock() defer b.lock.RUnlock() - return b.latestExecutionPayloadHeader(), nil + return b.latestExecutionPayloadHeaderVal(), nil } -// latestExecutionPayloadHeader of the beacon state. +// latestExecutionPayloadHeaderVal of the beacon state. // This assumes that a lock is already held on BeaconState. -func (b *BeaconState) latestExecutionPayloadHeader() *ethpb.ExecutionPayloadHeader { - if !b.hasInnerState() { - return nil - } - - return ethpb.CopyExecutionPayloadHeader(b.state.LatestExecutionPayloadHeader) +func (b *BeaconState) latestExecutionPayloadHeaderVal() *ethpb.ExecutionPayloadHeader { + return ethpb.CopyExecutionPayloadHeader(b.latestExecutionPayloadHeader) } diff --git a/beacon-chain/state/state-native/v3/getters_randao.go b/beacon-chain/state/state-native/v3/getters_randao.go index 660e330ab..75f028e5c 100644 --- a/beacon-chain/state/state-native/v3/getters_randao.go +++ b/beacon-chain/state/state-native/v3/getters_randao.go @@ -1,67 +1,52 @@ package v3 import ( - "github.com/prysmaticlabs/prysm/encoding/bytesutil" + "fmt" ) // RandaoMixes of block proposers on the beacon chain. func (b *BeaconState) RandaoMixes() [][]byte { - if !b.hasInnerState() { - return nil - } - if b.state.RandaoMixes == nil { + if b.randaoMixes == nil { return nil } b.lock.RLock() defer b.lock.RUnlock() - return b.randaoMixes() -} - -// randaoMixes of block proposers on the beacon chain. -// This assumes that a lock is already held on BeaconState. -func (b *BeaconState) randaoMixes() [][]byte { - if !b.hasInnerState() { - return nil - } - - return bytesutil.SafeCopy2dBytes(b.state.RandaoMixes) + 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.hasInnerState() { - return nil, ErrNilInnerState - } - if b.state.RandaoMixes == nil { + if b.randaoMixes == nil { return nil, nil } b.lock.RLock() defer b.lock.RUnlock() - return b.randaoMixAtIndex(idx) + 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) ([]byte, error) { - if !b.hasInnerState() { - return nil, ErrNilInnerState +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 bytesutil.SafeCopyRootAtIndex(b.state.RandaoMixes, idx) + return b.randaoMixes[idx], nil } // RandaoMixesLength returns the length of the randao mixes slice. func (b *BeaconState) RandaoMixesLength() int { - if !b.hasInnerState() { - return 0 - } - if b.state.RandaoMixes == nil { + if b.randaoMixes == nil { return 0 } @@ -74,12 +59,9 @@ func (b *BeaconState) RandaoMixesLength() int { // 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.hasInnerState() { - return 0 - } - if b.state.RandaoMixes == nil { + if b.randaoMixes == nil { return 0 } - return len(b.state.RandaoMixes) + return len(b.randaoMixes) } diff --git a/beacon-chain/state/state-native/v3/getters_state.go b/beacon-chain/state/state-native/v3/getters_state.go index 51d6a3d80..7658c4cba 100644 --- a/beacon-chain/state/state-native/v3/getters_state.go +++ b/beacon-chain/state/state-native/v3/getters_state.go @@ -1,127 +1,136 @@ package v3 import ( - "github.com/pkg/errors" - "github.com/prysmaticlabs/prysm/encoding/bytesutil" + "fmt" + ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ) -// InnerStateUnsafe returns the pointer value of the underlying +// ToProtoUnsafe returns the pointer value of the underlying // beacon state proto object, bypassing immutability. Use with care. -func (b *BeaconState) InnerStateUnsafe() interface{} { +func (b *BeaconState) ToProtoUnsafe() interface{} { if b == nil { return nil } - return b.state + + 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, + } } -// CloneInnerState the beacon state into a protobuf for usage. -func (b *BeaconState) CloneInnerState() interface{} { - if b == nil || b.state == 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() - return ðpb.BeaconStateBellatrix{ - GenesisTime: b.genesisTime(), - GenesisValidatorsRoot: b.genesisValidatorRoot(), - Slot: b.slot(), - Fork: b.fork(), - LatestBlockHeader: b.latestBlockHeader(), - BlockRoots: b.blockRoots(), - StateRoots: b.stateRoots(), - HistoricalRoots: b.historicalRoots(), - Eth1Data: b.eth1Data(), - Eth1DataVotes: b.eth1DataVotes(), - Eth1DepositIndex: b.eth1DepositIndex(), - Validators: b.validators(), - Balances: b.balances(), - RandaoMixes: b.randaoMixes(), - Slashings: b.slashings(), - CurrentEpochParticipation: b.currentEpochParticipation(), - PreviousEpochParticipation: b.previousEpochParticipation(), - JustificationBits: b.justificationBits(), - PreviousJustifiedCheckpoint: b.previousJustifiedCheckpoint(), - CurrentJustifiedCheckpoint: b.currentJustifiedCheckpoint(), - FinalizedCheckpoint: b.finalizedCheckpoint(), - InactivityScores: b.inactivityScores(), - CurrentSyncCommittee: b.currentSyncCommittee(), - NextSyncCommittee: b.nextSyncCommittee(), - LatestExecutionPayloadHeader: b.latestExecutionPayloadHeader(), - } -} -// hasInnerState detects if the internal reference to the state data structure -// is populated correctly. Returns false if nil. -func (b *BeaconState) hasInnerState() bool { - return b != nil && b.state != nil + 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.hasInnerState() { - return nil - } - if b.state.StateRoots == nil { + if b.stateRoots == nil { return nil } b.lock.RLock() defer b.lock.RUnlock() - return b.stateRoots() -} - -// StateRoots kept track of in the beacon state. -// This assumes that a lock is already held on BeaconState. -func (b *BeaconState) stateRoots() [][]byte { - if !b.hasInnerState() { - return nil - } - return bytesutil.SafeCopy2dBytes(b.state.StateRoots) + 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.hasInnerState() { - return nil, ErrNilInnerState - } - if b.state.StateRoots == nil { + if b.stateRoots == nil { return nil, nil } b.lock.RLock() defer b.lock.RUnlock() - return b.stateRootAtIndex(idx) + 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) ([]byte, error) { - if !b.hasInnerState() { - return nil, ErrNilInnerState +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 bytesutil.SafeCopyRootAtIndex(b.state.StateRoots, idx) + + return b.stateRoots[idx], nil } -// MarshalSSZ marshals the underlying beacon state to bytes. -func (b *BeaconState) MarshalSSZ() ([]byte, error) { - if !b.hasInnerState() { - return nil, errors.New("nil beacon state") - } - return b.state.MarshalSSZ() +// 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() } -// ProtobufBeaconState 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 ProtobufBeaconState(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 +// 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 index 38faf4ac1..9d3bf39b0 100644 --- a/beacon-chain/state/state-native/v3/getters_sync_committee.go +++ b/beacon-chain/state/state-native/v3/getters_sync_committee.go @@ -5,56 +5,40 @@ import ( ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ) -// currentSyncCommittee of the current sync committee in beacon chain state. +// currentSyncCommitteeVal of the current sync committee in beacon chain state. // This assumes that a lock is already held on BeaconState. -func (b *BeaconState) currentSyncCommittee() *ethpb.SyncCommittee { - if !b.hasInnerState() { - return nil - } - - return CopySyncCommittee(b.state.CurrentSyncCommittee) +func (b *BeaconState) currentSyncCommitteeVal() *ethpb.SyncCommittee { + return CopySyncCommittee(b.currentSyncCommittee) } -// nextSyncCommittee of the next sync committee in beacon chain state. +// nextSyncCommitteeVal of the next sync committee in beacon chain state. // This assumes that a lock is already held on BeaconState. -func (b *BeaconState) nextSyncCommittee() *ethpb.SyncCommittee { - if !b.hasInnerState() { - return nil - } - - return CopySyncCommittee(b.state.NextSyncCommittee) +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) { - if !b.hasInnerState() { - return nil, nil - } - b.lock.RLock() defer b.lock.RUnlock() - if b.state.CurrentSyncCommittee == nil { + if b.currentSyncCommittee == nil { return nil, nil } - return b.currentSyncCommittee(), nil + return b.currentSyncCommitteeVal(), nil } // NextSyncCommittee of the next sync committee in beacon chain state. func (b *BeaconState) NextSyncCommittee() (*ethpb.SyncCommittee, error) { - if !b.hasInnerState() { - return nil, nil - } - b.lock.RLock() defer b.lock.RUnlock() - if b.state.NextSyncCommittee == nil { + if b.nextSyncCommittee == nil { return nil, nil } - return b.nextSyncCommittee(), nil + return b.nextSyncCommitteeVal(), nil } // CopySyncCommittee copies the provided sync committee object. diff --git a/beacon-chain/state/state-native/v3/getters_test.go b/beacon-chain/state/state-native/v3/getters_test.go index 0357ef13d..a9d20f2bf 100644 --- a/beacon-chain/state/state-native/v3/getters_test.go +++ b/beacon-chain/state/state-native/v3/getters_test.go @@ -1,7 +1,6 @@ package v3 import ( - "runtime/debug" "sync" "testing" @@ -30,66 +29,6 @@ func TestBeaconState_SlotDataRace(t *testing.T) { wg.Wait() } -func TestNilState_NoPanic(t *testing.T) { - var st *BeaconState - defer func() { - if r := recover(); r != nil { - t.Errorf("Method panicked when it was not supposed to: %v\n%v\n", r, string(debug.Stack())) - } - }() - // retrieve elements from nil state - _ = st.GenesisTime() - _ = st.GenesisValidatorRoot() - _ = st.GenesisUnixTime() - _ = st.GenesisValidatorRoot() - _ = st.Slot() - _ = st.Fork() - _ = st.LatestBlockHeader() - _ = st.ParentRoot() - _ = st.BlockRoots() - _, err := st.BlockRootAtIndex(0) - _ = err - _ = st.StateRoots() - _ = st.HistoricalRoots() - _ = st.Eth1Data() - _ = st.Eth1DataVotes() - _ = st.Eth1DepositIndex() - _, err = st.ValidatorAtIndex(0) - _ = err - _, err = st.ValidatorAtIndexReadOnly(0) - _ = err - _, _ = st.ValidatorIndexByPubkey([fieldparams.BLSPubkeyLength]byte{}) - _ = st.PubkeyAtIndex(0) - _ = st.NumValidators() - _ = st.Balances() - _, err = st.BalanceAtIndex(0) - _ = err - _ = st.BalancesLength() - _ = st.RandaoMixes() - _, err = st.RandaoMixAtIndex(0) - _ = err - _ = st.RandaoMixesLength() - _ = st.Slashings() - _, err = st.CurrentEpochParticipation() - _ = err - _, err = st.PreviousEpochParticipation() - _ = err - _ = st.JustificationBits() - _ = st.PreviousJustifiedCheckpoint() - _ = st.CurrentJustifiedCheckpoint() - _ = st.FinalizedCheckpoint() - _, err = st.CurrentEpochParticipation() - _ = err - _, err = st.PreviousEpochParticipation() - _ = err - _, err = st.InactivityScores() - _ = err - _, err = st.CurrentSyncCommittee() - _ = err - _, err = st.NextSyncCommittee() - _ = err -} - func TestBeaconState_ValidatorByPubkey(t *testing.T) { keyCreator := func(input []byte) [fieldparams.BLSPubkeyLength]byte { nKey := [fieldparams.BLSPubkeyLength]byte{} diff --git a/beacon-chain/state/state-native/v3/getters_validator.go b/beacon-chain/state/state-native/v3/getters_validator.go index 11c9d810f..4e90d4510 100644 --- a/beacon-chain/state/state-native/v3/getters_validator.go +++ b/beacon-chain/state/state-native/v3/getters_validator.go @@ -32,32 +32,26 @@ func (e *ValidatorIndexOutOfRangeError) Error() string { // Validators participating in consensus on the beacon chain. func (b *BeaconState) Validators() []*ethpb.Validator { - if !b.hasInnerState() { - return nil - } - if b.state.Validators == nil { + if b.validators == nil { return nil } b.lock.RLock() defer b.lock.RUnlock() - return b.validators() + return b.validatorsVal() } -// validators participating in consensus on the beacon chain. +// validatorsVal participating in consensus on the beacon chain. // This assumes that a lock is already held on BeaconState. -func (b *BeaconState) validators() []*ethpb.Validator { - if !b.hasInnerState() { - return nil - } - if b.state.Validators == nil { +func (b *BeaconState) validatorsVal() []*ethpb.Validator { + if b.validators == nil { return nil } - res := make([]*ethpb.Validator, len(b.state.Validators)) + res := make([]*ethpb.Validator, len(b.validators)) for i := 0; i < len(res); i++ { - val := b.state.Validators[i] + val := b.validators[i] if val == nil { continue } @@ -70,16 +64,13 @@ func (b *BeaconState) validators() []*ethpb.Validator { // 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.hasInnerState() { - return nil - } - if b.state.Validators == nil { + if b.validators == nil { return nil } - res := make([]*ethpb.Validator, len(b.state.Validators)) + res := make([]*ethpb.Validator, len(b.validators)) for i := 0; i < len(res); i++ { - validator := b.state.Validators[i] + validator := b.validators[i] if validator == nil { continue } @@ -91,13 +82,10 @@ func (b *BeaconState) validatorsReferences() []*ethpb.Validator { // ValidatorAtIndex is the validator at the provided index. func (b *BeaconState) ValidatorAtIndex(idx types.ValidatorIndex) (*ethpb.Validator, error) { - if !b.hasInnerState() { - return nil, ErrNilInnerState - } - if b.state.Validators == nil { + if b.validators == nil { return ðpb.Validator{}, nil } - if uint64(len(b.state.Validators)) <= uint64(idx) { + if uint64(len(b.validators)) <= uint64(idx) { e := NewValidatorIndexOutOfRangeError(idx) return nil, &e } @@ -105,20 +93,17 @@ func (b *BeaconState) ValidatorAtIndex(idx types.ValidatorIndex) (*ethpb.Validat b.lock.RLock() defer b.lock.RUnlock() - val := b.state.Validators[idx] + 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.hasInnerState() { - return nil, ErrNilInnerState - } - if b.state.Validators == nil { + if b.validators == nil { return nil, state.ErrNilValidatorsInState } - if uint64(len(b.state.Validators)) <= uint64(idx) { + if uint64(len(b.validators)) <= uint64(idx) { e := NewValidatorIndexOutOfRangeError(idx) return nil, &e } @@ -126,7 +111,7 @@ func (b *BeaconState) ValidatorAtIndexReadOnly(idx types.ValidatorIndex) (state. b.lock.RLock() defer b.lock.RUnlock() - return v1.NewValidator(b.state.Validators[idx]) + return v1.NewValidator(b.validators[idx]) } // ValidatorIndexByPubkey returns a given validator by its 48-byte public key. @@ -136,7 +121,7 @@ func (b *BeaconState) ValidatorIndexByPubkey(key [fieldparams.BLSPubkeyLength]by } b.lock.RLock() defer b.lock.RUnlock() - numOfVals := len(b.state.Validators) + numOfVals := len(b.validators) idx, ok := b.valMapHandler.Get(key) if ok && numOfVals <= int(idx) { @@ -148,43 +133,34 @@ func (b *BeaconState) ValidatorIndexByPubkey(key [fieldparams.BLSPubkeyLength]by // PubkeyAtIndex returns the pubkey at the given // validator index. func (b *BeaconState) PubkeyAtIndex(idx types.ValidatorIndex) [fieldparams.BLSPubkeyLength]byte { - if !b.hasInnerState() { - return [fieldparams.BLSPubkeyLength]byte{} - } - if uint64(idx) >= uint64(len(b.state.Validators)) { + if uint64(idx) >= uint64(len(b.validators)) { return [fieldparams.BLSPubkeyLength]byte{} } b.lock.RLock() defer b.lock.RUnlock() - if b.state.Validators[idx] == nil { + if b.validators[idx] == nil { return [fieldparams.BLSPubkeyLength]byte{} } - return bytesutil.ToBytes48(b.state.Validators[idx].PublicKey) + return bytesutil.ToBytes48(b.validators[idx].PublicKey) } // NumValidators returns the size of the validator registry. func (b *BeaconState) NumValidators() int { - if !b.hasInnerState() { - return 0 - } b.lock.RLock() defer b.lock.RUnlock() - return len(b.state.Validators) + 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.hasInnerState() { - return ErrNilInnerState - } - if b.state.Validators == nil { + if b.validators == nil { return errors.New("nil validators in state") } b.lock.RLock() - validators := b.state.Validators + validators := b.validators b.lock.RUnlock() for i, v := range validators { @@ -201,58 +177,46 @@ func (b *BeaconState) ReadFromEveryValidator(f func(idx int, val state.ReadOnlyV // Balances of validators participating in consensus on the beacon chain. func (b *BeaconState) Balances() []uint64 { - if !b.hasInnerState() { - return nil - } - if b.state.Balances == nil { + if b.balances == nil { return nil } b.lock.RLock() defer b.lock.RUnlock() - return b.balances() + return b.balancesVal() } -// balances of validators participating in consensus on the beacon chain. +// balancesVal of validators participating in consensus on the beacon chain. // This assumes that a lock is already held on BeaconState. -func (b *BeaconState) balances() []uint64 { - if !b.hasInnerState() { - return nil - } - if b.state.Balances == nil { +func (b *BeaconState) balancesVal() []uint64 { + if b.balances == nil { return nil } - res := make([]uint64, len(b.state.Balances)) - copy(res, b.state.Balances) + 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.hasInnerState() { - return 0, ErrNilInnerState - } - if b.state.Balances == nil { + if b.balances == nil { return 0, nil } b.lock.RLock() defer b.lock.RUnlock() - if uint64(len(b.state.Balances)) <= uint64(idx) { + if uint64(len(b.balances)) <= uint64(idx) { return 0, fmt.Errorf("index of %d does not exist", idx) } - return b.state.Balances[idx], nil + return b.balances[idx], nil } // BalancesLength returns the length of the balances slice. func (b *BeaconState) BalancesLength() int { - if !b.hasInnerState() { - return 0 - } - if b.state.Balances == nil { + if b.balances == nil { return 0 } @@ -264,60 +228,48 @@ func (b *BeaconState) BalancesLength() int { // Slashings of validators on the beacon chain. func (b *BeaconState) Slashings() []uint64 { - if !b.hasInnerState() { - return nil - } - if b.state.Slashings == nil { + if b.slashings == nil { return nil } b.lock.RLock() defer b.lock.RUnlock() - return b.slashings() + return b.slashingsVal() } -// slashings of validators on the beacon chain. +// slashingsVal of validators on the beacon chain. // This assumes that a lock is already held on BeaconState. -func (b *BeaconState) slashings() []uint64 { - if !b.hasInnerState() { - return nil - } - if b.state.Slashings == nil { +func (b *BeaconState) slashingsVal() []uint64 { + if b.slashings == nil { return nil } - res := make([]uint64, len(b.state.Slashings)) - copy(res, b.state.Slashings) + res := make([]uint64, len(b.slashings)) + copy(res, b.slashings) return res } -// inactivityScores of validators participating in consensus on the beacon chain. +// inactivityScoresVal of validators participating in consensus on the beacon chain. // This assumes that a lock is already held on BeaconState. -func (b *BeaconState) inactivityScores() []uint64 { - if !b.hasInnerState() { - return nil - } - if b.state.InactivityScores == nil { +func (b *BeaconState) inactivityScoresVal() []uint64 { + if b.inactivityScores == nil { return nil } - res := make([]uint64, len(b.state.InactivityScores)) - copy(res, b.state.InactivityScores) + 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.hasInnerState() { - return nil, nil - } - if b.state.InactivityScores == nil { + if b.inactivityScores == nil { return nil, nil } b.lock.RLock() defer b.lock.RUnlock() - return b.inactivityScores(), nil + return b.inactivityScoresVal(), nil } diff --git a/beacon-chain/state/state-native/v3/proofs.go b/beacon-chain/state/state-native/v3/proofs.go index 0a3e4eddb..ec98401fc 100644 --- a/beacon-chain/state/state-native/v3/proofs.go +++ b/beacon-chain/state/state-native/v3/proofs.go @@ -68,7 +68,7 @@ func (b *BeaconState) FinalizedRootProof(ctx context.Context) ([][]byte, error) if err := b.recomputeDirtyFields(ctx); err != nil { return nil, err } - cpt := b.state.FinalizedCheckpoint + 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. diff --git a/beacon-chain/state/state-native/v3/proofs_test.go b/beacon-chain/state/state-native/v3/proofs_test.go index f7724e686..818bf17df 100644 --- a/beacon-chain/state/state-native/v3/proofs_test.go +++ b/beacon-chain/state/state-native/v3/proofs_test.go @@ -4,7 +4,7 @@ import ( "context" "testing" - v3 "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/v3" + 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" diff --git a/beacon-chain/state/state-native/v3/setters_block.go b/beacon-chain/state/state-native/v3/setters_block.go index 81fa29f32..3781a1336 100644 --- a/beacon-chain/state/state-native/v3/setters_block.go +++ b/beacon-chain/state/state-native/v3/setters_block.go @@ -3,19 +3,18 @@ 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 { - if !b.hasInnerState() { - return ErrNilInnerState - } b.lock.Lock() defer b.lock.Unlock() - b.state.LatestBlockHeader = ethpb.CopyBeaconBlockHeader(val) + b.latestBlockHeader = ethpb.CopyBeaconBlockHeader(val) b.markFieldAsDirty(latestBlockHeader) return nil } @@ -23,16 +22,18 @@ func (b *BeaconState) SetLatestBlockHeader(val *ethpb.BeaconBlockHeader) error { // 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 { - if !b.hasInnerState() { - return ErrNilInnerState - } b.lock.Lock() defer b.lock.Unlock() b.sharedFieldReferences[blockRoots].MinusRef() b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1) - b.state.BlockRoots = val + 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 @@ -41,26 +42,24 @@ func (b *BeaconState) SetBlockRoots(val [][]byte) error { // 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 !b.hasInnerState() { - return ErrNilInnerState - } - if uint64(len(b.state.BlockRoots)) <= idx { + if uint64(len(b.blockRoots)) <= idx { return fmt.Errorf("invalid index provided %d", idx) } b.lock.Lock() defer b.lock.Unlock() - r := b.state.BlockRoots + r := b.blockRoots if ref := b.sharedFieldReferences[blockRoots]; ref.Refs() > 1 { // Copy elements in underlying array by reference. - r = make([][]byte, len(b.state.BlockRoots)) - copy(r, b.state.BlockRoots) + roots := *b.blockRoots + rootsCopy := roots + r = &rootsCopy ref.MinusRef() b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1) } - r[idx] = blockRoot[:] - b.state.BlockRoots = r + r[idx] = blockRoot + b.blockRoots = r b.markFieldAsDirty(blockRoots) b.addDirtyIndices(blockRoots, []uint64{idx}) diff --git a/beacon-chain/state/state-native/v3/setters_checkpoint.go b/beacon-chain/state/state-native/v3/setters_checkpoint.go index 601f89dab..5286103be 100644 --- a/beacon-chain/state/state-native/v3/setters_checkpoint.go +++ b/beacon-chain/state/state-native/v3/setters_checkpoint.go @@ -7,52 +7,40 @@ import ( // SetJustificationBits for the beacon state. func (b *BeaconState) SetJustificationBits(val bitfield.Bitvector4) error { - if !b.hasInnerState() { - return ErrNilInnerState - } b.lock.Lock() defer b.lock.Unlock() - b.state.JustificationBits = val + b.justificationBits = val b.markFieldAsDirty(justificationBits) return nil } // SetPreviousJustifiedCheckpoint for the beacon state. func (b *BeaconState) SetPreviousJustifiedCheckpoint(val *ethpb.Checkpoint) error { - if !b.hasInnerState() { - return ErrNilInnerState - } b.lock.Lock() defer b.lock.Unlock() - b.state.PreviousJustifiedCheckpoint = val + b.previousJustifiedCheckpoint = val b.markFieldAsDirty(previousJustifiedCheckpoint) return nil } // SetCurrentJustifiedCheckpoint for the beacon state. func (b *BeaconState) SetCurrentJustifiedCheckpoint(val *ethpb.Checkpoint) error { - if !b.hasInnerState() { - return ErrNilInnerState - } b.lock.Lock() defer b.lock.Unlock() - b.state.CurrentJustifiedCheckpoint = val + b.currentJustifiedCheckpoint = val b.markFieldAsDirty(currentJustifiedCheckpoint) return nil } // SetFinalizedCheckpoint for the beacon state. func (b *BeaconState) SetFinalizedCheckpoint(val *ethpb.Checkpoint) error { - if !b.hasInnerState() { - return ErrNilInnerState - } b.lock.Lock() defer b.lock.Unlock() - b.state.FinalizedCheckpoint = val + b.finalizedCheckpoint = val b.markFieldAsDirty(finalizedCheckpoint) return nil } diff --git a/beacon-chain/state/state-native/v3/setters_eth1.go b/beacon-chain/state/state-native/v3/setters_eth1.go index 315bafe4b..4167599ef 100644 --- a/beacon-chain/state/state-native/v3/setters_eth1.go +++ b/beacon-chain/state/state-native/v3/setters_eth1.go @@ -7,13 +7,10 @@ import ( // SetEth1Data for the beacon state. func (b *BeaconState) SetEth1Data(val *ethpb.Eth1Data) error { - if !b.hasInnerState() { - return ErrNilInnerState - } b.lock.Lock() defer b.lock.Unlock() - b.state.Eth1Data = val + b.eth1Data = val b.markFieldAsDirty(eth1Data) return nil } @@ -21,16 +18,13 @@ func (b *BeaconState) SetEth1Data(val *ethpb.Eth1Data) error { // 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 { - if !b.hasInnerState() { - return ErrNilInnerState - } b.lock.Lock() defer b.lock.Unlock() b.sharedFieldReferences[eth1DataVotes].MinusRef() b.sharedFieldReferences[eth1DataVotes] = stateutil.NewRef(1) - b.state.Eth1DataVotes = val + b.eth1DataVotes = val b.markFieldAsDirty(eth1DataVotes) b.rebuildTrie[eth1DataVotes] = true return nil @@ -38,13 +32,10 @@ func (b *BeaconState) SetEth1DataVotes(val []*ethpb.Eth1Data) error { // SetEth1DepositIndex for the beacon state. func (b *BeaconState) SetEth1DepositIndex(val uint64) error { - if !b.hasInnerState() { - return ErrNilInnerState - } b.lock.Lock() defer b.lock.Unlock() - b.state.Eth1DepositIndex = val + b.eth1DepositIndex = val b.markFieldAsDirty(eth1DepositIndex) return nil } @@ -52,23 +43,20 @@ func (b *BeaconState) SetEth1DepositIndex(val uint64) error { // AppendEth1DataVotes for the beacon state. Appends the new value // to the the end of list. func (b *BeaconState) AppendEth1DataVotes(val *ethpb.Eth1Data) error { - if !b.hasInnerState() { - return ErrNilInnerState - } b.lock.Lock() defer b.lock.Unlock() - votes := b.state.Eth1DataVotes + votes := b.eth1DataVotes if b.sharedFieldReferences[eth1DataVotes].Refs() > 1 { // Copy elements in underlying array by reference. - votes = make([]*ethpb.Eth1Data, len(b.state.Eth1DataVotes)) - copy(votes, b.state.Eth1DataVotes) + votes = make([]*ethpb.Eth1Data, len(b.eth1DataVotes)) + copy(votes, b.eth1DataVotes) b.sharedFieldReferences[eth1DataVotes].MinusRef() b.sharedFieldReferences[eth1DataVotes] = stateutil.NewRef(1) } - b.state.Eth1DataVotes = append(votes, val) + b.eth1DataVotes = append(votes, val) b.markFieldAsDirty(eth1DataVotes) - b.addDirtyIndices(eth1DataVotes, []uint64{uint64(len(b.state.Eth1DataVotes) - 1)}) + b.addDirtyIndices(eth1DataVotes, []uint64{uint64(len(b.eth1DataVotes) - 1)}) return nil } diff --git a/beacon-chain/state/state-native/v3/setters_misc.go b/beacon-chain/state/state-native/v3/setters_misc.go index 27839ff99..9e14660b9 100644 --- a/beacon-chain/state/state-native/v3/setters_misc.go +++ b/beacon-chain/state/state-native/v3/setters_misc.go @@ -6,7 +6,9 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" stateTypes "github.com/prysmaticlabs/prysm/beacon-chain/state/types" "github.com/prysmaticlabs/prysm/config/features" + fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" "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" ) @@ -43,7 +45,7 @@ func (b *BeaconState) SetGenesisTime(val uint64) error { b.lock.Lock() defer b.lock.Unlock() - b.state.GenesisTime = val + b.genesisTime = val b.markFieldAsDirty(genesisTime) return nil } @@ -53,29 +55,26 @@ func (b *BeaconState) SetGenesisValidatorRoot(val []byte) error { b.lock.Lock() defer b.lock.Unlock() - b.state.GenesisValidatorsRoot = val + if len(val) != fieldparams.RootLength { + return errors.New("incorrect validator root length") + } + b.genesisValidatorsRoot = bytesutil.ToBytes32(val) b.markFieldAsDirty(genesisValidatorRoot) return nil } // SetSlot for the beacon state. func (b *BeaconState) SetSlot(val types.Slot) error { - if !b.hasInnerState() { - return ErrNilInnerState - } b.lock.Lock() defer b.lock.Unlock() - b.state.Slot = val + b.slot = val b.markFieldAsDirty(slot) return nil } // SetFork version for the beacon chain. func (b *BeaconState) SetFork(val *ethpb.Fork) error { - if !b.hasInnerState() { - return ErrNilInnerState - } b.lock.Lock() defer b.lock.Unlock() @@ -83,7 +82,7 @@ func (b *BeaconState) SetFork(val *ethpb.Fork) error { if !ok { return errors.New("proto.Clone did not return a fork proto") } - b.state.Fork = fk + b.fork = fk b.markFieldAsDirty(fork) return nil } @@ -91,16 +90,17 @@ func (b *BeaconState) SetFork(val *ethpb.Fork) error { // 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 { - if !b.hasInnerState() { - return ErrNilInnerState - } b.lock.Lock() defer b.lock.Unlock() b.sharedFieldReferences[historicalRoots].MinusRef() b.sharedFieldReferences[historicalRoots] = stateutil.NewRef(1) - b.state.HistoricalRoots = val + roots := make([][fieldparams.RootLength]byte, len(val)) + for i, r := range val { + copy(roots[i][:], r) + } + b.historicalRoots = roots b.markFieldAsDirty(historicalRoots) return nil } @@ -108,21 +108,18 @@ func (b *BeaconState) SetHistoricalRoots(val [][]byte) error { // AppendHistoricalRoots for the beacon state. Appends the new value // to the the end of list. func (b *BeaconState) AppendHistoricalRoots(root [32]byte) error { - if !b.hasInnerState() { - return ErrNilInnerState - } b.lock.Lock() defer b.lock.Unlock() - roots := b.state.HistoricalRoots + roots := b.historicalRoots if b.sharedFieldReferences[historicalRoots].Refs() > 1 { - roots = make([][]byte, len(b.state.HistoricalRoots)) - copy(roots, b.state.HistoricalRoots) + roots = make([][fieldparams.RootLength]byte, len(b.historicalRoots)) + copy(roots, b.historicalRoots) b.sharedFieldReferences[historicalRoots].MinusRef() b.sharedFieldReferences[historicalRoots] = stateutil.NewRef(1) } - b.state.HistoricalRoots = append(roots, root[:]) + b.historicalRoots = append(roots, root) b.markFieldAsDirty(historicalRoots) return nil } diff --git a/beacon-chain/state/state-native/v3/setters_participation.go b/beacon-chain/state/state-native/v3/setters_participation.go index c5aa72c16..b3cca9cd3 100644 --- a/beacon-chain/state/state-native/v3/setters_participation.go +++ b/beacon-chain/state/state-native/v3/setters_participation.go @@ -7,16 +7,13 @@ import ( // 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 { - if !b.hasInnerState() { - return ErrNilInnerState - } b.lock.Lock() defer b.lock.Unlock() b.sharedFieldReferences[previousEpochParticipationBits].MinusRef() b.sharedFieldReferences[previousEpochParticipationBits] = stateutil.NewRef(1) - b.state.PreviousEpochParticipation = val + b.previousEpochParticipation = val b.markFieldAsDirty(previousEpochParticipationBits) b.rebuildTrie[previousEpochParticipationBits] = true return nil @@ -25,16 +22,13 @@ func (b *BeaconState) SetPreviousParticipationBits(val []byte) error { // 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 { - if !b.hasInnerState() { - return ErrNilInnerState - } b.lock.Lock() defer b.lock.Unlock() b.sharedFieldReferences[currentEpochParticipationBits].MinusRef() b.sharedFieldReferences[currentEpochParticipationBits] = stateutil.NewRef(1) - b.state.CurrentEpochParticipation = val + b.currentEpochParticipation = val b.markFieldAsDirty(currentEpochParticipationBits) b.rebuildTrie[currentEpochParticipationBits] = true return nil @@ -43,47 +37,41 @@ func (b *BeaconState) SetCurrentParticipationBits(val []byte) error { // AppendCurrentParticipationBits for the beacon state. Appends the new value // to the the end of list. func (b *BeaconState) AppendCurrentParticipationBits(val byte) error { - if !b.hasInnerState() { - return ErrNilInnerState - } b.lock.Lock() defer b.lock.Unlock() - participation := b.state.CurrentEpochParticipation + participation := b.currentEpochParticipation if b.sharedFieldReferences[currentEpochParticipationBits].Refs() > 1 { // Copy elements in underlying array by reference. - participation = make([]byte, len(b.state.CurrentEpochParticipation)) - copy(participation, b.state.CurrentEpochParticipation) + participation = make([]byte, len(b.currentEpochParticipation)) + copy(participation, b.currentEpochParticipation) b.sharedFieldReferences[currentEpochParticipationBits].MinusRef() b.sharedFieldReferences[currentEpochParticipationBits] = stateutil.NewRef(1) } - b.state.CurrentEpochParticipation = append(participation, val) + b.currentEpochParticipation = append(participation, val) b.markFieldAsDirty(currentEpochParticipationBits) - b.addDirtyIndices(currentEpochParticipationBits, []uint64{uint64(len(b.state.CurrentEpochParticipation) - 1)}) + 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 { - if !b.hasInnerState() { - return ErrNilInnerState - } b.lock.Lock() defer b.lock.Unlock() - bits := b.state.PreviousEpochParticipation + bits := b.previousEpochParticipation if b.sharedFieldReferences[previousEpochParticipationBits].Refs() > 1 { - bits = make([]byte, len(b.state.PreviousEpochParticipation)) - copy(bits, b.state.PreviousEpochParticipation) + bits = make([]byte, len(b.previousEpochParticipation)) + copy(bits, b.previousEpochParticipation) b.sharedFieldReferences[previousEpochParticipationBits].MinusRef() b.sharedFieldReferences[previousEpochParticipationBits] = stateutil.NewRef(1) } - b.state.PreviousEpochParticipation = append(bits, val) + b.previousEpochParticipation = append(bits, val) b.markFieldAsDirty(previousEpochParticipationBits) - b.addDirtyIndices(previousEpochParticipationBits, []uint64{uint64(len(b.state.PreviousEpochParticipation) - 1)}) + b.addDirtyIndices(previousEpochParticipationBits, []uint64{uint64(len(b.previousEpochParticipation) - 1)}) 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 index 516db0f50..d4a998251 100644 --- a/beacon-chain/state/state-native/v3/setters_payload_header.go +++ b/beacon-chain/state/state-native/v3/setters_payload_header.go @@ -4,13 +4,10 @@ import ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" // SetLatestExecutionPayloadHeader for the beacon state. func (b *BeaconState) SetLatestExecutionPayloadHeader(val *ethpb.ExecutionPayloadHeader) error { - if !b.hasInnerState() { - return ErrNilInnerState - } b.lock.Lock() defer b.lock.Unlock() - b.state.LatestExecutionPayloadHeader = val + 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 index 017ca6a57..456d8572f 100644 --- a/beacon-chain/state/state-native/v3/setters_randao.go +++ b/beacon-chain/state/state-native/v3/setters_randao.go @@ -2,22 +2,27 @@ 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 { - if !b.hasInnerState() { - return ErrNilInnerState - } b.lock.Lock() defer b.lock.Unlock() b.sharedFieldReferences[randaoMixes].MinusRef() b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1) - b.state.RandaoMixes = val + 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 @@ -26,26 +31,24 @@ func (b *BeaconState) SetRandaoMixes(val [][]byte) error { // UpdateRandaoMixesAtIndex for the beacon state. Updates the randao mixes // at a specific index to a new value. func (b *BeaconState) UpdateRandaoMixesAtIndex(idx uint64, val []byte) error { - if !b.hasInnerState() { - return ErrNilInnerState - } - if uint64(len(b.state.RandaoMixes)) <= idx { + if uint64(len(b.randaoMixes)) <= idx { return errors.Errorf("invalid index provided %d", idx) } b.lock.Lock() defer b.lock.Unlock() - mixes := b.state.RandaoMixes + mixes := b.randaoMixes if refs := b.sharedFieldReferences[randaoMixes].Refs(); refs > 1 { // Copy elements in underlying array by reference. - mixes = make([][]byte, len(b.state.RandaoMixes)) - copy(mixes, b.state.RandaoMixes) + m := *b.randaoMixes + mCopy := m + mixes = &mCopy b.sharedFieldReferences[randaoMixes].MinusRef() b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1) } - mixes[idx] = val - b.state.RandaoMixes = mixes + mixes[idx] = bytesutil.ToBytes32(val) + b.randaoMixes = mixes b.markFieldAsDirty(randaoMixes) b.addDirtyIndices(randaoMixes, []uint64{idx}) diff --git a/beacon-chain/state/state-native/v3/setters_state.go b/beacon-chain/state/state-native/v3/setters_state.go index 24a83d2fa..f53561869 100644 --- a/beacon-chain/state/state-native/v3/setters_state.go +++ b/beacon-chain/state/state-native/v3/setters_state.go @@ -2,22 +2,26 @@ 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 { - if !b.hasInnerState() { - return ErrNilInnerState - } b.lock.Lock() defer b.lock.Unlock() b.sharedFieldReferences[stateRoots].MinusRef() b.sharedFieldReferences[stateRoots] = stateutil.NewRef(1) - b.state.StateRoots = val + 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 @@ -26,12 +30,8 @@ func (b *BeaconState) SetStateRoots(val [][]byte) error { // UpdateStateRootAtIndex for the beacon state. Updates the state root // at a specific index to a new value. func (b *BeaconState) UpdateStateRootAtIndex(idx uint64, stateRoot [32]byte) error { - if !b.hasInnerState() { - return ErrNilInnerState - } - b.lock.RLock() - if uint64(len(b.state.StateRoots)) <= idx { + if uint64(len(b.stateRoots)) <= idx { b.lock.RUnlock() return errors.Errorf("invalid index provided %d", idx) } @@ -41,17 +41,18 @@ func (b *BeaconState) UpdateStateRootAtIndex(idx uint64, stateRoot [32]byte) err defer b.lock.Unlock() // Check if we hold the only reference to the shared state roots slice. - r := b.state.StateRoots + r := b.stateRoots if ref := b.sharedFieldReferences[stateRoots]; ref.Refs() > 1 { // Copy elements in underlying array by reference. - r = make([][]byte, len(b.state.StateRoots)) - copy(r, b.state.StateRoots) + roots := *b.stateRoots + rootsCopy := roots + r = &rootsCopy ref.MinusRef() b.sharedFieldReferences[stateRoots] = stateutil.NewRef(1) } - r[idx] = stateRoot[:] - b.state.StateRoots = r + r[idx] = stateRoot + b.stateRoots = r b.markFieldAsDirty(stateRoots) b.addDirtyIndices(stateRoots, []uint64{idx}) diff --git a/beacon-chain/state/state-native/v3/setters_sync_committee.go b/beacon-chain/state/state-native/v3/setters_sync_committee.go index 7b5fa8372..2cf694a82 100644 --- a/beacon-chain/state/state-native/v3/setters_sync_committee.go +++ b/beacon-chain/state/state-native/v3/setters_sync_committee.go @@ -6,26 +6,20 @@ import ( // SetCurrentSyncCommittee for the beacon state. func (b *BeaconState) SetCurrentSyncCommittee(val *ethpb.SyncCommittee) error { - if !b.hasInnerState() { - return ErrNilInnerState - } b.lock.Lock() defer b.lock.Unlock() - b.state.CurrentSyncCommittee = val + b.currentSyncCommittee = val b.markFieldAsDirty(currentSyncCommittee) return nil } // SetNextSyncCommittee for the beacon state. func (b *BeaconState) SetNextSyncCommittee(val *ethpb.SyncCommittee) error { - if !b.hasInnerState() { - return ErrNilInnerState - } b.lock.Lock() defer b.lock.Unlock() - b.state.NextSyncCommittee = val + b.nextSyncCommittee = val b.markFieldAsDirty(nextSyncCommittee) return nil } diff --git a/beacon-chain/state/state-native/v3/setters_test.go b/beacon-chain/state/state-native/v3/setters_test.go index 3199de8e1..81184d7c5 100644 --- a/beacon-chain/state/state-native/v3/setters_test.go +++ b/beacon-chain/state/state-native/v3/setters_test.go @@ -8,79 +8,19 @@ import ( types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/go-bitfield" "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" - stateTypes "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/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/testing/assert" - "github.com/prysmaticlabs/prysm/testing/require" ) -func TestAppendBeyondIndicesLimit(t *testing.T) { - 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[:] - } - payload := ðpb.ExecutionPayloadHeader{ - ParentHash: make([]byte, 32), - FeeRecipient: make([]byte, 20), - StateRoot: make([]byte, 32), - ReceiptRoot: make([]byte, 32), - LogsBloom: make([]byte, 256), - Random: make([]byte, 32), - BaseFeePerGas: make([]byte, 32), - BlockHash: make([]byte, 32), - TransactionsRoot: make([]byte, 32), - } - st, err := InitializeFromProto(ðpb.BeaconStateBellatrix{ - Slot: 1, - CurrentEpochParticipation: []byte{}, - PreviousEpochParticipation: []byte{}, - Validators: []*ethpb.Validator{}, - Eth1Data: ðpb.Eth1Data{}, - BlockRoots: mockblockRoots, - StateRoots: mockstateRoots, - RandaoMixes: mockrandaoMixes, - LatestExecutionPayloadHeader: payload, - }) - require.NoError(t, err) - _, err = st.HashTreeRoot(context.Background()) - require.NoError(t, err) - for i := stateTypes.FieldIndex(0); i < stateTypes.FieldIndex(params.BeaconConfig().BeaconStateBellatrixFieldCount); i++ { - st.dirtyFields[i] = true - } - _, err = st.HashTreeRoot(context.Background()) - require.NoError(t, err) - for i := 0; i < 10; i++ { - assert.NoError(t, st.AppendValidator(ðpb.Validator{})) - } - assert.Equal(t, false, st.rebuildTrie[validators]) - assert.NotEqual(t, len(st.dirtyIndices[validators]), 0) - - for i := 0; i < indicesLimit; i++ { - assert.NoError(t, st.AppendValidator(ðpb.Validator{})) - } - assert.Equal(t, true, st.rebuildTrie[validators]) - assert.Equal(t, len(st.dirtyIndices[validators]), 0) -} - 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 := [32]byte{} + someRoot := [fieldparams.RootLength]byte{} someKey := [fieldparams.BLSPubkeyLength]byte{} copy(someRoot[:], strconv.Itoa(int(i))) copy(someKey[:], strconv.Itoa(int(i))) @@ -115,44 +55,44 @@ func TestBeaconState_AppendBalanceWithTrie(t *testing.T) { pubKeys = append(pubKeys, bytesutil.PadTo([]byte{}, params.BeaconConfig().BLSPubkeyLength)) } payload := ðpb.ExecutionPayloadHeader{ - ParentHash: make([]byte, 32), + ParentHash: make([]byte, fieldparams.RootLength), FeeRecipient: make([]byte, 20), - StateRoot: make([]byte, 32), - ReceiptRoot: make([]byte, 32), + StateRoot: make([]byte, fieldparams.RootLength), + ReceiptRoot: make([]byte, fieldparams.RootLength), LogsBloom: make([]byte, 256), - Random: make([]byte, 32), - BaseFeePerGas: make([]byte, 32), - BlockHash: make([]byte, 32), - TransactionsRoot: make([]byte, 32), + Random: make([]byte, fieldparams.RootLength), + BaseFeePerGas: make([]byte, fieldparams.RootLength), + BlockHash: make([]byte, fieldparams.RootLength), + TransactionsRoot: make([]byte, fieldparams.RootLength), } st, err := InitializeFromProto(ðpb.BeaconStateBellatrix{ Slot: 1, - GenesisValidatorsRoot: make([]byte, 32), + GenesisValidatorsRoot: make([]byte, fieldparams.RootLength), Fork: ðpb.Fork{ PreviousVersion: make([]byte, 4), CurrentVersion: make([]byte, 4), Epoch: 0, }, LatestBlockHeader: ðpb.BeaconBlockHeader{ - ParentRoot: make([]byte, 32), - StateRoot: make([]byte, 32), - BodyRoot: make([]byte, 32), + 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, 32), - BlockHash: make([]byte, 32), + 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, 32)}, - CurrentJustifiedCheckpoint: ðpb.Checkpoint{Root: make([]byte, 32)}, - FinalizedCheckpoint: ðpb.Checkpoint{Root: make([]byte, 32)}, + 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, @@ -179,7 +119,7 @@ func TestBeaconState_AppendBalanceWithTrie(t *testing.T) { _, err = st.HashTreeRoot(context.Background()) assert.NoError(t, err) newRt := bytesutil.ToBytes32(st.merkleLayers[0][balances]) - wantedRt, err := stateutil.Uint64ListRootWithRegistryLimit(st.state.Balances) + wantedRt, err := stateutil.Uint64ListRootWithRegistryLimit(st.balances) assert.NoError(t, err) assert.Equal(t, wantedRt, newRt, "state roots are unequal") } diff --git a/beacon-chain/state/state-native/v3/setters_validator.go b/beacon-chain/state/state-native/v3/setters_validator.go index f621ff81b..8e1174e1d 100644 --- a/beacon-chain/state/state-native/v3/setters_validator.go +++ b/beacon-chain/state/state-native/v3/setters_validator.go @@ -11,29 +11,23 @@ import ( // 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 { - if !b.hasInnerState() { - return ErrNilInnerState - } b.lock.Lock() defer b.lock.Unlock() - b.state.Validators = val + 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.state.Validators) + 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 { - if !b.hasInnerState() { - return ErrNilInnerState - } b.lock.Lock() - v := b.state.Validators + v := b.validators if ref := b.sharedFieldReferences[validators]; ref.Refs() > 1 { v = b.validatorsReferences() ref.MinusRef() @@ -55,7 +49,7 @@ func (b *BeaconState) ApplyToEveryValidator(f func(idx int, val *ethpb.Validator b.lock.Lock() defer b.lock.Unlock() - b.state.Validators = v + b.validators = v b.markFieldAsDirty(validators) b.addDirtyIndices(validators, changedVals) @@ -65,16 +59,13 @@ func (b *BeaconState) ApplyToEveryValidator(f func(idx int, val *ethpb.Validator // 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 !b.hasInnerState() { - return ErrNilInnerState - } - if uint64(len(b.state.Validators)) <= uint64(idx) { + if uint64(len(b.validators)) <= uint64(idx) { return errors.Errorf("invalid index provided %d", idx) } b.lock.Lock() defer b.lock.Unlock() - v := b.state.Validators + v := b.validators if ref := b.sharedFieldReferences[validators]; ref.Refs() > 1 { v = b.validatorsReferences() ref.MinusRef() @@ -82,7 +73,7 @@ func (b *BeaconState) UpdateValidatorAtIndex(idx types.ValidatorIndex, val *ethp } v[idx] = val - b.state.Validators = v + b.validators = v b.markFieldAsDirty(validators) b.addDirtyIndices(validators, []uint64{uint64(idx)}) @@ -92,16 +83,13 @@ func (b *BeaconState) UpdateValidatorAtIndex(idx types.ValidatorIndex, val *ethp // 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 { - if !b.hasInnerState() { - return ErrNilInnerState - } b.lock.Lock() defer b.lock.Unlock() b.sharedFieldReferences[balances].MinusRef() b.sharedFieldReferences[balances] = stateutil.NewRef(1) - b.state.Balances = val + b.balances = val b.markFieldAsDirty(balances) b.rebuildTrie[balances] = true return nil @@ -110,24 +98,21 @@ func (b *BeaconState) SetBalances(val []uint64) error { // UpdateBalancesAtIndex for the beacon state. This method updates the balance // at a specific index to a new value. func (b *BeaconState) UpdateBalancesAtIndex(idx types.ValidatorIndex, val uint64) error { - if !b.hasInnerState() { - return ErrNilInnerState - } - if uint64(len(b.state.Balances)) <= uint64(idx) { + if uint64(len(b.balances)) <= uint64(idx) { return errors.Errorf("invalid index provided %d", idx) } b.lock.Lock() defer b.lock.Unlock() - bals := b.state.Balances + bals := b.balances if b.sharedFieldReferences[balances].Refs() > 1 { - bals = b.balances() + bals = b.balancesVal() b.sharedFieldReferences[balances].MinusRef() b.sharedFieldReferences[balances] = stateutil.NewRef(1) } bals[idx] = val - b.state.Balances = bals + b.balances = bals b.markFieldAsDirty(balances) b.addDirtyIndices(balances, []uint64{uint64(idx)}) return nil @@ -136,16 +121,13 @@ func (b *BeaconState) UpdateBalancesAtIndex(idx types.ValidatorIndex, val uint64 // 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 { - if !b.hasInnerState() { - return ErrNilInnerState - } b.lock.Lock() defer b.lock.Unlock() b.sharedFieldReferences[slashings].MinusRef() b.sharedFieldReferences[slashings] = stateutil.NewRef(1) - b.state.Slashings = val + b.slashings = val b.markFieldAsDirty(slashings) return nil } @@ -153,25 +135,22 @@ func (b *BeaconState) SetSlashings(val []uint64) error { // 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 !b.hasInnerState() { - return ErrNilInnerState - } - if uint64(len(b.state.Slashings)) <= idx { + if uint64(len(b.slashings)) <= idx { return errors.Errorf("invalid index provided %d", idx) } b.lock.Lock() defer b.lock.Unlock() - s := b.state.Slashings + s := b.slashings if b.sharedFieldReferences[slashings].Refs() > 1 { - s = b.slashings() + s = b.slashingsVal() b.sharedFieldReferences[slashings].MinusRef() b.sharedFieldReferences[slashings] = stateutil.NewRef(1) } s[idx] = val - b.state.Slashings = s + b.slashings = s b.markFieldAsDirty(slashings) return nil @@ -180,13 +159,10 @@ func (b *BeaconState) UpdateSlashingsAtIndex(idx, val uint64) error { // AppendValidator for the beacon state. Appends the new value // to the the end of list. func (b *BeaconState) AppendValidator(val *ethpb.Validator) error { - if !b.hasInnerState() { - return ErrNilInnerState - } b.lock.Lock() defer b.lock.Unlock() - vals := b.state.Validators + vals := b.validators if b.sharedFieldReferences[validators].Refs() > 1 { vals = b.validatorsReferences() b.sharedFieldReferences[validators].MinusRef() @@ -194,8 +170,8 @@ func (b *BeaconState) AppendValidator(val *ethpb.Validator) error { } // append validator to slice - b.state.Validators = append(vals, val) - valIdx := types.ValidatorIndex(len(b.state.Validators) - 1) + b.validators = append(vals, val) + valIdx := types.ValidatorIndex(len(b.validators) - 1) b.valMapHandler.Set(bytesutil.ToBytes48(val.PublicKey), valIdx) @@ -207,21 +183,18 @@ func (b *BeaconState) AppendValidator(val *ethpb.Validator) error { // AppendBalance for the beacon state. Appends the new value // to the the end of list. func (b *BeaconState) AppendBalance(bal uint64) error { - if !b.hasInnerState() { - return ErrNilInnerState - } b.lock.Lock() defer b.lock.Unlock() - bals := b.state.Balances + bals := b.balances if b.sharedFieldReferences[balances].Refs() > 1 { - bals = b.balances() + bals = b.balancesVal() b.sharedFieldReferences[balances].MinusRef() b.sharedFieldReferences[balances] = stateutil.NewRef(1) } - b.state.Balances = append(bals, bal) - balIdx := len(b.state.Balances) - 1 + b.balances = append(bals, bal) + balIdx := len(b.balances) - 1 b.markFieldAsDirty(balances) b.addDirtyIndices(balances, []uint64{uint64(balIdx)}) return nil @@ -229,20 +202,17 @@ func (b *BeaconState) AppendBalance(bal uint64) error { // AppendInactivityScore for the beacon state. func (b *BeaconState) AppendInactivityScore(s uint64) error { - if !b.hasInnerState() { - return ErrNilInnerState - } b.lock.Lock() defer b.lock.Unlock() - scores := b.state.InactivityScores + scores := b.inactivityScores if b.sharedFieldReferences[inactivityScores].Refs() > 1 { - scores = b.inactivityScores() + scores = b.inactivityScoresVal() b.sharedFieldReferences[inactivityScores].MinusRef() b.sharedFieldReferences[inactivityScores] = stateutil.NewRef(1) } - b.state.InactivityScores = append(scores, s) + b.inactivityScores = append(scores, s) b.markFieldAsDirty(inactivityScores) return nil } @@ -250,16 +220,13 @@ func (b *BeaconState) AppendInactivityScore(s uint64) error { // 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 { - if !b.hasInnerState() { - return ErrNilInnerState - } b.lock.Lock() defer b.lock.Unlock() b.sharedFieldReferences[inactivityScores].MinusRef() b.sharedFieldReferences[inactivityScores] = stateutil.NewRef(1) - b.state.InactivityScores = val + b.inactivityScores = val b.markFieldAsDirty(inactivityScores) return nil } diff --git a/beacon-chain/state/state-native/v3/state_trie.go b/beacon-chain/state/state-native/v3/state_trie.go index e447329fa..e8b85e880 100644 --- a/beacon-chain/state/state-native/v3/state_trie.go +++ b/beacon-chain/state/state-native/v3/state_trie.go @@ -6,7 +6,9 @@ import ( "sort" "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/beacon-chain/state" + customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types" "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/fieldtrie" "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" "github.com/prysmaticlabs/prysm/beacon-chain/state/types" @@ -26,16 +28,58 @@ func InitializeFromProto(st *ethpb.BeaconStateBellatrix) (*BeaconState, error) { return InitializeFromProtoUnsafe(proto.Clone(st).(*ethpb.BeaconStateBellatrix)) } -// InitializeFromProtoUnsafe directly uses the beacon state protobuf pointer -// and sets it as the inner state of the BeaconState type. +// InitializeFromProtoUnsafe directly uses the beacon state protobuf fields +// and sets them as fields of the BeaconState type. func InitializeFromProtoUnsafe(st *ethpb.BeaconStateBellatrix) (*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().BeaconStateBellatrixFieldCount b := &BeaconState{ - state: st, + 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), @@ -74,49 +118,44 @@ func InitializeFromProtoUnsafe(st *ethpb.BeaconStateBellatrix) (*BeaconState, er // Copy returns a deep copy of the beacon state. func (b *BeaconState) Copy() state.BeaconState { - if !b.hasInnerState() { - return nil - } - b.lock.RLock() defer b.lock.RUnlock() fieldCount := params.BeaconConfig().BeaconStateBellatrixFieldCount dst := &BeaconState{ - state: ðpb.BeaconStateBellatrix{ - // Primitive types, safe to copy. - GenesisTime: b.state.GenesisTime, - Slot: b.state.Slot, - Eth1DepositIndex: b.state.Eth1DepositIndex, + // Primitive types, safe to copy. + genesisTime: b.genesisTime, + slot: b.slot, + eth1DepositIndex: b.eth1DepositIndex, - // Large arrays, infrequently changed, constant size. - RandaoMixes: b.state.RandaoMixes, - StateRoots: b.state.StateRoots, - BlockRoots: b.state.BlockRoots, - Slashings: b.state.Slashings, - Eth1DataVotes: b.state.Eth1DataVotes, + // 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.state.Validators, - Balances: b.state.Balances, - HistoricalRoots: b.state.HistoricalRoots, - PreviousEpochParticipation: b.state.PreviousEpochParticipation, - CurrentEpochParticipation: b.state.CurrentEpochParticipation, - InactivityScores: b.state.InactivityScores, + // 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(), - // Everything else, too small to be concerned about, constant size. - Fork: b.fork(), - LatestBlockHeader: b.latestBlockHeader(), - Eth1Data: b.eth1Data(), - JustificationBits: b.justificationBits(), - PreviousJustifiedCheckpoint: b.previousJustifiedCheckpoint(), - CurrentJustifiedCheckpoint: b.currentJustifiedCheckpoint(), - FinalizedCheckpoint: b.finalizedCheckpoint(), - GenesisValidatorsRoot: b.genesisValidatorRoot(), - CurrentSyncCommittee: b.currentSyncCommittee(), - NextSyncCommittee: b.nextSyncCommittee(), - LatestExecutionPayloadHeader: b.latestExecutionPayloadHeader(), - }, dirtyFields: make(map[types.FieldIndex]bool, fieldCount), dirtyIndices: make(map[types.FieldIndex][]uint64, fieldCount), rebuildTrie: make(map[types.FieldIndex]bool, fieldCount), @@ -199,11 +238,12 @@ func (b *BeaconState) HashTreeRoot(ctx context.Context) ([32]byte, error) { b.lock.Lock() defer b.lock.Unlock() + if err := b.initializeMerkleLayers(ctx); err != nil { - return [32]byte{}, err + return [fieldparams.RootLength]byte{}, err } if err := b.recomputeDirtyFields(ctx); err != nil { - return [32]byte{}, err + return [fieldparams.RootLength]byte{}, err } return bytesutil.ToBytes32(b.merkleLayers[len(b.merkleLayers)-1][0]), nil } @@ -214,7 +254,11 @@ func (b *BeaconState) initializeMerkleLayers(ctx context.Context) error { if len(b.merkleLayers) > 0 { return nil } - fieldRoots, err := computeFieldRoots(ctx, b.state) + 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 } @@ -262,27 +306,27 @@ func (b *BeaconState) FieldReferencesCount() map[string]uint64 { // IsNil checks if the state and the underlying proto // object are nil. func (b *BeaconState) IsNil() bool { - return b == nil || b.state == nil + return b == nil } func (b *BeaconState) rootSelector(field types.FieldIndex) ([32]byte, error) { hasher := hash.CustomSHA256Hasher() switch field { case genesisTime: - return ssz.Uint64Root(b.state.GenesisTime), nil + return ssz.Uint64Root(b.genesisTime), nil case genesisValidatorRoot: - return bytesutil.ToBytes32(b.state.GenesisValidatorsRoot), nil + return b.genesisValidatorsRoot, nil case slot: - return ssz.Uint64Root(uint64(b.state.Slot)), nil + return ssz.Uint64Root(uint64(b.slot)), nil case eth1DepositIndex: - return ssz.Uint64Root(b.state.Eth1DepositIndex), nil + return ssz.Uint64Root(b.eth1DepositIndex), nil case fork: - return ssz.ForkRoot(b.state.Fork) + return ssz.ForkRoot(b.fork) case latestBlockHeader: - return stateutil.BlockHeaderRoot(b.state.LatestBlockHeader) + return stateutil.BlockHeaderRoot(b.latestBlockHeader) case blockRoots: if b.rebuildTrie[field] { - err := b.resetFieldTrie(field, b.state.BlockRoots, fieldparams.BlockRootsLength) + err := b.resetFieldTrie(field, b.blockRoots, fieldparams.BlockRootsLength) if err != nil { return [32]byte{}, err } @@ -290,10 +334,10 @@ func (b *BeaconState) rootSelector(field types.FieldIndex) ([32]byte, error) { delete(b.rebuildTrie, field) return b.stateFieldLeaves[field].TrieRoot() } - return b.recomputeFieldTrie(blockRoots, b.state.BlockRoots) + return b.recomputeFieldTrie(blockRoots, b.blockRoots) case stateRoots: if b.rebuildTrie[field] { - err := b.resetFieldTrie(field, b.state.StateRoots, fieldparams.StateRootsLength) + err := b.resetFieldTrie(field, b.stateRoots, fieldparams.StateRootsLength) if err != nil { return [32]byte{}, err } @@ -301,16 +345,20 @@ func (b *BeaconState) rootSelector(field types.FieldIndex) ([32]byte, error) { delete(b.rebuildTrie, field) return b.stateFieldLeaves[field].TrieRoot() } - return b.recomputeFieldTrie(stateRoots, b.state.StateRoots) + return b.recomputeFieldTrie(stateRoots, b.stateRoots) case historicalRoots: - return ssz.ByteArrayRootWithLimit(b.state.HistoricalRoots, fieldparams.HistoricalRootsLength) + 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.state.Eth1Data) + return stateutil.Eth1Root(hasher, b.eth1Data) case eth1DataVotes: if b.rebuildTrie[field] { err := b.resetFieldTrie( field, - b.state.Eth1DataVotes, + b.eth1DataVotes, fieldparams.Eth1DataVotesLength, ) if err != nil { @@ -320,10 +368,10 @@ func (b *BeaconState) rootSelector(field types.FieldIndex) ([32]byte, error) { delete(b.rebuildTrie, field) return b.stateFieldLeaves[field].TrieRoot() } - return b.recomputeFieldTrie(field, b.state.Eth1DataVotes) + return b.recomputeFieldTrie(field, b.eth1DataVotes) case validators: if b.rebuildTrie[field] { - err := b.resetFieldTrie(field, b.state.Validators, fieldparams.ValidatorRegistryLimit) + err := b.resetFieldTrie(field, b.validators, fieldparams.ValidatorRegistryLimit) if err != nil { return [32]byte{}, err } @@ -331,12 +379,12 @@ func (b *BeaconState) rootSelector(field types.FieldIndex) ([32]byte, error) { delete(b.rebuildTrie, validators) return b.stateFieldLeaves[field].TrieRoot() } - return b.recomputeFieldTrie(validators, b.state.Validators) + return b.recomputeFieldTrie(validators, b.validators) case balances: - return stateutil.Uint64ListRootWithRegistryLimit(b.state.Balances) + return stateutil.Uint64ListRootWithRegistryLimit(b.balances) case randaoMixes: if b.rebuildTrie[field] { - err := b.resetFieldTrie(field, b.state.RandaoMixes, fieldparams.RandaoMixesLength) + err := b.resetFieldTrie(field, b.randaoMixes, fieldparams.RandaoMixesLength) if err != nil { return [32]byte{}, err } @@ -344,29 +392,29 @@ func (b *BeaconState) rootSelector(field types.FieldIndex) ([32]byte, error) { delete(b.rebuildTrie, field) return b.stateFieldLeaves[field].TrieRoot() } - return b.recomputeFieldTrie(randaoMixes, b.state.RandaoMixes) + return b.recomputeFieldTrie(randaoMixes, b.randaoMixes) case slashings: - return ssz.SlashingsRoot(b.state.Slashings) + return ssz.SlashingsRoot(b.slashings) case previousEpochParticipationBits: - return stateutil.ParticipationBitsRoot(b.state.PreviousEpochParticipation) + return stateutil.ParticipationBitsRoot(b.previousEpochParticipation) case currentEpochParticipationBits: - return stateutil.ParticipationBitsRoot(b.state.CurrentEpochParticipation) + return stateutil.ParticipationBitsRoot(b.currentEpochParticipation) case justificationBits: - return bytesutil.ToBytes32(b.state.JustificationBits), nil + return bytesutil.ToBytes32(b.justificationBits), nil case previousJustifiedCheckpoint: - return ssz.CheckpointRoot(hasher, b.state.PreviousJustifiedCheckpoint) + return ssz.CheckpointRoot(hasher, b.previousJustifiedCheckpoint) case currentJustifiedCheckpoint: - return ssz.CheckpointRoot(hasher, b.state.CurrentJustifiedCheckpoint) + return ssz.CheckpointRoot(hasher, b.currentJustifiedCheckpoint) case finalizedCheckpoint: - return ssz.CheckpointRoot(hasher, b.state.FinalizedCheckpoint) + return ssz.CheckpointRoot(hasher, b.finalizedCheckpoint) case inactivityScores: - return stateutil.Uint64ListRootWithRegistryLimit(b.state.InactivityScores) + return stateutil.Uint64ListRootWithRegistryLimit(b.inactivityScores) case currentSyncCommittee: - return stateutil.SyncCommitteeRoot(b.state.CurrentSyncCommittee) + return stateutil.SyncCommitteeRoot(b.currentSyncCommittee) case nextSyncCommittee: - return stateutil.SyncCommitteeRoot(b.state.NextSyncCommittee) + return stateutil.SyncCommitteeRoot(b.nextSyncCommittee) case latestExecutionPayloadHeader: - return b.state.LatestExecutionPayloadHeader.HashTreeRoot() + return b.latestExecutionPayloadHeader.HashTreeRoot() } return [32]byte{}, errors.New("invalid field index provided") } diff --git a/beacon-chain/state/state-native/v3/state_trie_test.go b/beacon-chain/state/state-native/v3/state_trie_test.go index 863f191f7..10d7b8adc 100644 --- a/beacon-chain/state/state-native/v3/state_trie_test.go +++ b/beacon-chain/state/state-native/v3/state_trie_test.go @@ -25,7 +25,7 @@ func TestValidatorMap_DistinctCopy(t *testing.T) { count := uint64(100) vals := make([]*ethpb.Validator, 0, count) for i := uint64(1); i < count; i++ { - someRoot := [32]byte{} + someRoot := [fieldparams.RootLength]byte{} someKey := [fieldparams.BLSPubkeyLength]byte{} copy(someRoot[:], strconv.Itoa(int(i))) copy(someKey[:], strconv.Itoa(int(i))) @@ -89,7 +89,7 @@ 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{} + someRoot := [fieldparams.RootLength]byte{} someKey := [fieldparams.BLSPubkeyLength]byte{} copy(someRoot[:], strconv.Itoa(int(i))) copy(someKey[:], strconv.Itoa(int(i))) @@ -119,7 +119,7 @@ func TestBeaconState_NoDeadlock(t *testing.T) { for _, f := range st.stateFieldLeaves { f.Lock() if f.Empty() { - f.InsertFieldLayer(make([][]*[32]byte, 10)) + f.InsertFieldLayer(make([][]*[fieldparams.RootLength]byte, 10)) } f.Unlock() f.FieldReference().AddRef() diff --git a/beacon-chain/state/state-native/v3/types.go b/beacon-chain/state/state-native/v3/types.go index d896c768c..05302f2c8 100644 --- a/beacon-chain/state/state-native/v3/types.go +++ b/beacon-chain/state/state-native/v3/types.go @@ -1,14 +1,8 @@ package v3 import ( - "sync" - - "github.com/pkg/errors" - "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/fieldtrie" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" "github.com/prysmaticlabs/prysm/beacon-chain/state/types" "github.com/prysmaticlabs/prysm/config/params" - ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ) func init() { @@ -57,21 +51,3 @@ const ( // fieldMap keeps track of each field // to its corresponding data type. var fieldMap map[types.FieldIndex]types.DataType - -// ErrNilInnerState returns when the inner state is nil and no copy set or get -// operations can be performed on state. -var ErrNilInnerState = errors.New("nil inner state") - -// 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 { - state *ethpb.BeaconStateBellatrix - 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/nogo_config.json b/nogo_config.json index 64f4ec647..bde6fafcb 100644 --- a/nogo_config.json +++ b/nogo_config.json @@ -148,7 +148,8 @@ }, "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/v2/generated.ssz.go": "Exclude generated SSZ file", + "beacon-chain/state/state-native/v3/generated.ssz.go": "Exclude generated SSZ file" } }, "properpermissions": {