Native beacon state: v2 (#10121)

Co-authored-by: Nishant Das <nishdas93@gmail.com>
This commit is contained in:
Radosław Kapka
2022-01-27 09:42:32 +01:00
committed by GitHub
parent 72817a6d0e
commit 9ee00f09a1
34 changed files with 1354 additions and 962 deletions

View File

@@ -1,7 +1,6 @@
package v1
import (
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/beacon-chain/state/types"
"github.com/prysmaticlabs/prysm/config/params"
@@ -29,10 +28,6 @@ func init() {
// 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")
// Field Aliases for values from the types package.
const (
genesisTime = types.GenesisTime

View File

@@ -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",
@@ -27,7 +29,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/v2",
visibility = [
"//beacon-chain:__subpackages__",
@@ -37,10 +43,12 @@ go_library(
],
deps = [
"//beacon-chain/state:go_default_library",
"//beacon-chain/state/fieldtrie:go_default_library",
"//beacon-chain/state/state-native/custom-types:go_default_library",
"//beacon-chain/state/state-native/fieldtrie: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/v1:go_default_library",
"//config/features:go_default_library",
"//config/fieldparams:go_default_library",
"//config/params:go_default_library",
@@ -50,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",
@@ -69,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/v2:go_default_library",
"//config/features:go_default_library",
"//config/fieldparams:go_default_library",
"//config/params:go_default_library",
@@ -90,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]",
],
)

View File

@@ -0,0 +1,53 @@
// +build !minimal
package v2
import (
"sync"
eth2types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/go-bitfield"
"github.com/prysmaticlabs/prysm/beacon-chain/state/fieldtrie"
customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
"github.com/prysmaticlabs/prysm/beacon-chain/state/types"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
)
// BeaconState defines a struct containing utilities for the eth2 chain state, defining
// getters and setters for its respective values and helpful functions such as HashTreeRoot().
type BeaconState struct {
genesisTime uint64 `ssz-gen:"true"`
genesisValidatorsRoot customtypes.Byte32 `ssz-gen:"true" ssz-size:"32"`
slot eth2types.Slot `ssz-gen:"true"`
fork *ethpb.Fork `ssz-gen:"true"`
latestBlockHeader *ethpb.BeaconBlockHeader `ssz-gen:"true"`
blockRoots *customtypes.BlockRoots `ssz-gen:"true" ssz-size:"8192,32"`
stateRoots *customtypes.StateRoots `ssz-gen:"true" ssz-size:"8192,32"`
historicalRoots customtypes.HistoricalRoots `ssz-gen:"true" ssz-size:"?,32" ssz-max:"16777216"`
eth1Data *ethpb.Eth1Data `ssz-gen:"true"`
eth1DataVotes []*ethpb.Eth1Data `ssz-gen:"true" ssz-max:"2048"`
eth1DepositIndex uint64 `ssz-gen:"true"`
validators []*ethpb.Validator `ssz-gen:"true" ssz-max:"1099511627776"`
balances []uint64 `ssz-gen:"true" ssz-max:"1099511627776"`
randaoMixes *customtypes.RandaoMixes `ssz-gen:"true" ssz-size:"65536,32"`
slashings []uint64 `ssz-gen:"true" ssz-size:"8192"`
previousEpochParticipation []byte `ssz-gen:"true" ssz-max:"1099511627776"`
currentEpochParticipation []byte `ssz-gen:"true" ssz-max:"1099511627776"`
justificationBits bitfield.Bitvector4 `ssz-gen:"true" ssz-size:"1"`
previousJustifiedCheckpoint *ethpb.Checkpoint `ssz-gen:"true"`
currentJustifiedCheckpoint *ethpb.Checkpoint `ssz-gen:"true"`
finalizedCheckpoint *ethpb.Checkpoint `ssz-gen:"true"`
inactivityScores []uint64 `ssz-gen:"true" ssz-max:"1099511627776"`
currentSyncCommittee *ethpb.SyncCommittee `ssz-gen:"true"`
nextSyncCommittee *ethpb.SyncCommittee `ssz-gen:"true"`
lock sync.RWMutex
dirtyFields map[types.FieldIndex]bool
dirtyIndices map[types.FieldIndex][]uint64
stateFieldLeaves map[types.FieldIndex]*fieldtrie.FieldTrie
rebuildTrie map[types.FieldIndex]bool
valMapHandler *stateutil.ValidatorMapHandler
merkleLayers [][][]byte
sharedFieldReferences map[types.FieldIndex]*stateutil.Reference
}

View File

@@ -0,0 +1,86 @@
// +build !minimal
package v2
import (
"reflect"
"strconv"
"testing"
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
"github.com/prysmaticlabs/prysm/testing/assert"
"github.com/prysmaticlabs/prysm/testing/require"
)
func TestMainnetSszValuesAgainstFieldParams(t *testing.T) {
// Casting needed to avoid lock copy analyzer issue.
bs := (interface{})(BeaconState{})
bsType := reflect.TypeOf(bs)
f, ok := bsType.FieldByName("genesisValidatorsRoot")
require.Equal(t, true, ok, "Required field not found")
v := f.Tag.Get("ssz-size")
assert.Equal(t, strconv.Itoa(fieldparams.RootLength), v)
f, ok = bsType.FieldByName("blockRoots")
require.Equal(t, true, ok, "Required field not found")
v = f.Tag.Get("ssz-size")
assert.Equal(t, strconv.Itoa(fieldparams.BlockRootsLength)+","+strconv.Itoa(fieldparams.RootLength), v)
f, ok = bsType.FieldByName("stateRoots")
require.Equal(t, true, ok, "Required field not found")
v = f.Tag.Get("ssz-size")
assert.Equal(t, strconv.Itoa(fieldparams.StateRootsLength)+","+strconv.Itoa(fieldparams.RootLength), v)
f, ok = bsType.FieldByName("historicalRoots")
require.Equal(t, true, ok, "Required field not found")
v = f.Tag.Get("ssz-size")
assert.Equal(t, "?,"+strconv.Itoa(fieldparams.RootLength), v)
v = f.Tag.Get("ssz-max")
assert.Equal(t, strconv.Itoa(fieldparams.HistoricalRootsLength), v)
f, ok = bsType.FieldByName("eth1DataVotes")
require.Equal(t, true, ok, "Required field not found")
v = f.Tag.Get("ssz-max")
assert.Equal(t, strconv.Itoa(fieldparams.Eth1DataVotesLength), v)
f, ok = bsType.FieldByName("validators")
require.Equal(t, true, ok, "Required field not found")
v = f.Tag.Get("ssz-max")
assert.Equal(t, strconv.Itoa(fieldparams.ValidatorRegistryLimit), v)
f, ok = bsType.FieldByName("balances")
require.Equal(t, true, ok, "Required field not found")
v = f.Tag.Get("ssz-max")
assert.Equal(t, strconv.Itoa(fieldparams.ValidatorRegistryLimit), v)
f, ok = bsType.FieldByName("randaoMixes")
require.Equal(t, true, ok, "Required field not found")
v = f.Tag.Get("ssz-size")
assert.Equal(t, strconv.Itoa(fieldparams.RandaoMixesLength)+","+strconv.Itoa(fieldparams.RootLength), v)
f, ok = bsType.FieldByName("slashings")
require.Equal(t, true, ok, "Required field not found")
v = f.Tag.Get("ssz-size")
assert.Equal(t, strconv.Itoa(fieldparams.SlashingsLength), v)
f, ok = bsType.FieldByName("previousEpochParticipation")
require.Equal(t, true, ok, "Required field not found")
v = f.Tag.Get("ssz-max")
assert.Equal(t, strconv.Itoa(fieldparams.ValidatorRegistryLimit), v)
f, ok = bsType.FieldByName("currentEpochParticipation")
require.Equal(t, true, ok, "Required field not found")
v = f.Tag.Get("ssz-max")
assert.Equal(t, strconv.Itoa(fieldparams.ValidatorRegistryLimit), v)
f, ok = bsType.FieldByName("justificationBits")
require.Equal(t, true, ok, "Required field not found")
v = f.Tag.Get("ssz-size")
assert.Equal(t, "1", v)
f, ok = bsType.FieldByName("inactivityScores")
require.Equal(t, true, ok, "Required field not found")
v = f.Tag.Get("ssz-max")
assert.Equal(t, strconv.Itoa(fieldparams.ValidatorRegistryLimit), v)
}

View File

@@ -0,0 +1,53 @@
// +build minimal
package v2
import (
"sync"
eth2types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/go-bitfield"
"github.com/prysmaticlabs/prysm/beacon-chain/state/fieldtrie"
customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
"github.com/prysmaticlabs/prysm/beacon-chain/state/types"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
)
// BeaconState defines a struct containing utilities for the eth2 chain state, defining
// getters and setters for its respective values and helpful functions such as HashTreeRoot().
type BeaconState struct {
genesisTime uint64 `ssz-gen:"true"`
genesisValidatorsRoot customtypes.Byte32 `ssz-gen:"true" ssz-size:"32"`
slot eth2types.Slot `ssz-gen:"true"`
fork *ethpb.Fork `ssz-gen:"true"`
latestBlockHeader *ethpb.BeaconBlockHeader `ssz-gen:"true"`
blockRoots *customtypes.BlockRoots `ssz-gen:"true" ssz-size:"64,32"`
stateRoots *customtypes.StateRoots `ssz-gen:"true" ssz-size:"64,32"`
historicalRoots customtypes.HistoricalRoots `ssz-gen:"true" ssz-size:"?,32" ssz-max:"16777216"`
eth1Data *ethpb.Eth1Data `ssz-gen:"true"`
eth1DataVotes []*ethpb.Eth1Data `ssz-gen:"true" ssz-max:"32"`
eth1DepositIndex uint64 `ssz-gen:"true"`
validators []*ethpb.Validator `ssz-gen:"true" ssz-max:"1099511627776"`
balances []uint64 `ssz-gen:"true" ssz-max:"1099511627776"`
randaoMixes *customtypes.RandaoMixes `ssz-gen:"true" ssz-size:"64,32"`
slashings []uint64 `ssz-gen:"true" ssz-size:"64"`
previousEpochParticipation []byte `ssz-gen:"true" ssz-max:"1099511627776"`
currentEpochParticipation []byte `ssz-gen:"true" ssz-max:"1099511627776"`
justificationBits bitfield.Bitvector4 `ssz-gen:"true" ssz-size:"1"`
previousJustifiedCheckpoint *ethpb.Checkpoint `ssz-gen:"true"`
currentJustifiedCheckpoint *ethpb.Checkpoint `ssz-gen:"true"`
finalizedCheckpoint *ethpb.Checkpoint `ssz-gen:"true"`
inactivityScores []uint64 `ssz-gen:"true" ssz-max:"1099511627776"`
currentSyncCommittee *ethpb.SyncCommittee `ssz-gen:"true"`
nextSyncCommittee *ethpb.SyncCommittee `ssz-gen:"true"`
lock sync.RWMutex
dirtyFields map[types.FieldIndex]bool
dirtyIndices map[types.FieldIndex][]uint64
stateFieldLeaves map[types.FieldIndex]*fieldtrie.FieldTrie
rebuildTrie map[types.FieldIndex]bool
valMapHandler *stateutil.ValidatorMapHandler
merkleLayers [][][]byte
sharedFieldReferences map[types.FieldIndex]*stateutil.Reference
}

View File

@@ -0,0 +1,86 @@
// +build minimal
package v2
import (
"reflect"
"strconv"
"testing"
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
"github.com/prysmaticlabs/prysm/testing/assert"
"github.com/prysmaticlabs/prysm/testing/require"
)
func TestMinimalSszValuesAgainstFieldParams(t *testing.T) {
// Casting needed to avoid lock copy analyzer issue.
bs := (interface{})(BeaconState{})
bsType := reflect.TypeOf(bs)
f, ok := bsType.FieldByName("genesisValidatorsRoot")
require.Equal(t, true, ok, "Required field not found")
v := f.Tag.Get("ssz-size")
assert.Equal(t, strconv.Itoa(fieldparams.RootLength), v)
f, ok = bsType.FieldByName("blockRoots")
require.Equal(t, true, ok, "Required field not found")
v = f.Tag.Get("ssz-size")
assert.Equal(t, strconv.Itoa(fieldparams.BlockRootsLength)+","+strconv.Itoa(fieldparams.RootLength), v)
f, ok = bsType.FieldByName("stateRoots")
require.Equal(t, true, ok, "Required field not found")
v = f.Tag.Get("ssz-size")
assert.Equal(t, strconv.Itoa(fieldparams.StateRootsLength)+","+strconv.Itoa(fieldparams.RootLength), v)
f, ok = bsType.FieldByName("historicalRoots")
require.Equal(t, true, ok, "Required field not found")
v = f.Tag.Get("ssz-size")
assert.Equal(t, "?,"+strconv.Itoa(fieldparams.RootLength), v)
v = f.Tag.Get("ssz-max")
assert.Equal(t, strconv.Itoa(fieldparams.HistoricalRootsLength), v)
f, ok = bsType.FieldByName("eth1DataVotes")
require.Equal(t, true, ok, "Required field not found")
v = f.Tag.Get("ssz-max")
assert.Equal(t, strconv.Itoa(fieldparams.Eth1DataVotesLength), v)
f, ok = bsType.FieldByName("validators")
require.Equal(t, true, ok, "Required field not found")
v = f.Tag.Get("ssz-max")
assert.Equal(t, strconv.Itoa(fieldparams.ValidatorRegistryLimit), v)
f, ok = bsType.FieldByName("balances")
require.Equal(t, true, ok, "Required field not found")
v = f.Tag.Get("ssz-max")
assert.Equal(t, strconv.Itoa(fieldparams.ValidatorRegistryLimit), v)
f, ok = bsType.FieldByName("randaoMixes")
require.Equal(t, true, ok, "Required field not found")
v = f.Tag.Get("ssz-size")
assert.Equal(t, strconv.Itoa(fieldparams.RandaoMixesLength)+","+strconv.Itoa(fieldparams.RootLength), v)
f, ok = bsType.FieldByName("slashings")
require.Equal(t, true, ok, "Required field not found")
v = f.Tag.Get("ssz-size")
assert.Equal(t, strconv.Itoa(fieldparams.SlashingsLength), v)
f, ok = bsType.FieldByName("previousEpochParticipation")
require.Equal(t, true, ok, "Required field not found")
v = f.Tag.Get("ssz-max")
assert.Equal(t, strconv.Itoa(fieldparams.ValidatorRegistryLimit), v)
f, ok = bsType.FieldByName("currentEpochParticipation")
require.Equal(t, true, ok, "Required field not found")
v = f.Tag.Get("ssz-max")
assert.Equal(t, strconv.Itoa(fieldparams.ValidatorRegistryLimit), v)
f, ok = bsType.FieldByName("justificationBits")
require.Equal(t, true, ok, "Required field not found")
v = f.Tag.Get("ssz-size")
assert.Equal(t, "1", v)
f, ok = bsType.FieldByName("inactivityScores")
require.Equal(t, true, ok, "Required field not found")
v = f.Tag.Get("ssz-max")
assert.Equal(t, strconv.Itoa(fieldparams.ValidatorRegistryLimit), v)
}

View File

@@ -0,0 +1,505 @@
// Code generated by fastssz. DO NOT EDIT.
// Hash: 6a7886393e8874ccf57ea6c160647da09f5e541234a235ee71f3bf786d56a100
package v2
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(2736629)
// Field (0) 'genesisTime'
dst = ssz.MarshalUint64(dst, b.genesisTime)
// Field (1) 'genesisValidatorsRoot'
dst = append(dst, b.genesisValidatorsRoot[:]...)
// Field (2) 'slot'
dst = ssz.MarshalUint64(dst, uint64(b.slot))
// Field (3) 'fork'
if b.fork == nil {
b.fork = new(ethpb.Fork)
}
if dst, err = b.fork.MarshalSSZTo(dst); err != nil {
return
}
// Field (4) 'latestBlockHeader'
if b.latestBlockHeader == nil {
b.latestBlockHeader = new(ethpb.BeaconBlockHeader)
}
if dst, err = b.latestBlockHeader.MarshalSSZTo(dst); err != nil {
return
}
// Field (5) 'blockRoots'
for ii := 0; ii < 8192; ii++ {
dst = append(dst, b.blockRoots[ii][:]...)
}
// Field (6) 'stateRoots'
for ii := 0; ii < 8192; ii++ {
dst = append(dst, b.stateRoots[ii][:]...)
}
// Offset (7) 'historicalRoots'
dst = ssz.WriteOffset(dst, offset)
offset += len(b.historicalRoots) * 32
// Field (8) 'eth1Data'
if b.eth1Data == nil {
b.eth1Data = new(ethpb.Eth1Data)
}
if dst, err = b.eth1Data.MarshalSSZTo(dst); err != nil {
return
}
// Offset (9) 'eth1DataVotes'
dst = ssz.WriteOffset(dst, offset)
offset += len(b.eth1DataVotes) * 72
// Field (10) 'eth1DepositIndex'
dst = ssz.MarshalUint64(dst, b.eth1DepositIndex)
// Offset (11) 'validators'
dst = ssz.WriteOffset(dst, offset)
offset += len(b.validators) * 121
// Offset (12) 'balances'
dst = ssz.WriteOffset(dst, offset)
offset += len(b.balances) * 8
// Field (13) 'randaoMixes'
for ii := 0; ii < 65536; ii++ {
dst = append(dst, b.randaoMixes[ii][:]...)
}
// Field (14) 'slashings'
if len(b.slashings) != 8192 {
err = ssz.ErrVectorLength
return
}
for ii := 0; ii < 8192; ii++ {
dst = ssz.MarshalUint64(dst, b.slashings[ii])
}
// Offset (15) 'previousEpochParticipation'
dst = ssz.WriteOffset(dst, offset)
offset += len(b.previousEpochParticipation)
// Offset (16) 'currentEpochParticipation'
dst = ssz.WriteOffset(dst, offset)
offset += len(b.currentEpochParticipation)
// Field (17) 'justificationBits'
if len(b.justificationBits) != 1 {
err = ssz.ErrBytesLength
return
}
dst = append(dst, b.justificationBits...)
// Field (18) 'previousJustifiedCheckpoint'
if b.previousJustifiedCheckpoint == nil {
b.previousJustifiedCheckpoint = new(ethpb.Checkpoint)
}
if dst, err = b.previousJustifiedCheckpoint.MarshalSSZTo(dst); err != nil {
return
}
// Field (19) 'currentJustifiedCheckpoint'
if b.currentJustifiedCheckpoint == nil {
b.currentJustifiedCheckpoint = new(ethpb.Checkpoint)
}
if dst, err = b.currentJustifiedCheckpoint.MarshalSSZTo(dst); err != nil {
return
}
// Field (20) 'finalizedCheckpoint'
if b.finalizedCheckpoint == nil {
b.finalizedCheckpoint = new(ethpb.Checkpoint)
}
if dst, err = b.finalizedCheckpoint.MarshalSSZTo(dst); err != nil {
return
}
// Offset (21) 'inactivityScores'
dst = ssz.WriteOffset(dst, offset)
offset += len(b.inactivityScores) * 8
// Field (22) 'currentSyncCommittee'
if b.currentSyncCommittee == nil {
b.currentSyncCommittee = new(ethpb.SyncCommittee)
}
if dst, err = b.currentSyncCommittee.MarshalSSZTo(dst); err != nil {
return
}
// Field (23) 'nextSyncCommittee'
if b.nextSyncCommittee == nil {
b.nextSyncCommittee = new(ethpb.SyncCommittee)
}
if dst, err = b.nextSyncCommittee.MarshalSSZTo(dst); err != nil {
return
}
// Field (7) 'historicalRoots'
if len(b.historicalRoots) > 16777216 {
err = ssz.ErrListTooBig
return
}
for ii := 0; ii < len(b.historicalRoots); ii++ {
dst = append(dst, b.historicalRoots[ii][:]...)
}
// Field (9) 'eth1DataVotes'
if len(b.eth1DataVotes) > 2048 {
err = ssz.ErrListTooBig
return
}
for ii := 0; ii < len(b.eth1DataVotes); ii++ {
if dst, err = b.eth1DataVotes[ii].MarshalSSZTo(dst); err != nil {
return
}
}
// Field (11) 'validators'
if len(b.validators) > 1099511627776 {
err = ssz.ErrListTooBig
return
}
for ii := 0; ii < len(b.validators); ii++ {
if dst, err = b.validators[ii].MarshalSSZTo(dst); err != nil {
return
}
}
// Field (12) 'balances'
if len(b.balances) > 1099511627776 {
err = ssz.ErrListTooBig
return
}
for ii := 0; ii < len(b.balances); ii++ {
dst = ssz.MarshalUint64(dst, b.balances[ii])
}
// Field (15) 'previousEpochParticipation'
if len(b.previousEpochParticipation) > 1099511627776 {
err = ssz.ErrBytesLength
return
}
dst = append(dst, b.previousEpochParticipation...)
// Field (16) 'currentEpochParticipation'
if len(b.currentEpochParticipation) > 1099511627776 {
err = ssz.ErrBytesLength
return
}
dst = append(dst, b.currentEpochParticipation...)
// Field (21) 'inactivityScores'
if len(b.inactivityScores) > 1099511627776 {
err = ssz.ErrListTooBig
return
}
for ii := 0; ii < len(b.inactivityScores); ii++ {
dst = ssz.MarshalUint64(dst, b.inactivityScores[ii])
}
return
}
// UnmarshalSSZ ssz unmarshals the BeaconState object
func (b *BeaconState) UnmarshalSSZ(buf []byte) error {
var err error
size := uint64(len(buf))
if size < 2736629 {
return ssz.ErrSize
}
tail := buf
var o7, o9, o11, o12, o15, o16, o21 uint64
// Field (0) 'genesisTime'
b.genesisTime = ssz.UnmarshallUint64(buf[0:8])
// Field (1) 'genesisValidatorsRoot'
copy(b.genesisValidatorsRoot[:], buf[8:40])
// Field (2) 'slot'
b.slot = eth2types.Slot(ssz.UnmarshallUint64(buf[40:48]))
// Field (3) 'fork'
if b.fork == nil {
b.fork = new(ethpb.Fork)
}
if err = b.fork.UnmarshalSSZ(buf[48:64]); err != nil {
return err
}
// Field (4) 'latestBlockHeader'
if b.latestBlockHeader == nil {
b.latestBlockHeader = new(ethpb.BeaconBlockHeader)
}
if err = b.latestBlockHeader.UnmarshalSSZ(buf[64:176]); err != nil {
return err
}
// Field (5) 'blockRoots'
for ii := 0; ii < 8192; ii++ {
copy(b.blockRoots[ii][:], buf[176:262320][ii*32:(ii+1)*32])
}
// Field (6) 'stateRoots'
for ii := 0; ii < 8192; ii++ {
copy(b.stateRoots[ii][:], buf[262320:524464][ii*32:(ii+1)*32])
}
// Offset (7) 'historicalRoots'
if o7 = ssz.ReadOffset(buf[524464:524468]); o7 > size {
return ssz.ErrOffset
}
if o7 < 2736629 {
return ssz.ErrInvalidVariableOffset
}
// Field (8) 'eth1Data'
if b.eth1Data == nil {
b.eth1Data = new(ethpb.Eth1Data)
}
if err = b.eth1Data.UnmarshalSSZ(buf[524468:524540]); err != nil {
return err
}
// Offset (9) 'eth1DataVotes'
if o9 = ssz.ReadOffset(buf[524540:524544]); o9 > size || o7 > o9 {
return ssz.ErrOffset
}
// Field (10) 'eth1DepositIndex'
b.eth1DepositIndex = ssz.UnmarshallUint64(buf[524544:524552])
// Offset (11) 'validators'
if o11 = ssz.ReadOffset(buf[524552:524556]); o11 > size || o9 > o11 {
return ssz.ErrOffset
}
// Offset (12) 'balances'
if o12 = ssz.ReadOffset(buf[524556:524560]); o12 > size || o11 > o12 {
return ssz.ErrOffset
}
// Field (13) 'randaoMixes'
for ii := 0; ii < 65536; ii++ {
copy(b.randaoMixes[ii][:], buf[524560:2621712][ii*32:(ii+1)*32])
}
// Field (14) 'slashings'
b.slashings = ssz.ExtendUint64(b.slashings, 8192)
for ii := 0; ii < 8192; ii++ {
b.slashings[ii] = ssz.UnmarshallUint64(buf[2621712:2687248][ii*8 : (ii+1)*8])
}
// Offset (15) 'previousEpochParticipation'
if o15 = ssz.ReadOffset(buf[2687248:2687252]); o15 > size || o12 > o15 {
return ssz.ErrOffset
}
// Offset (16) 'currentEpochParticipation'
if o16 = ssz.ReadOffset(buf[2687252:2687256]); o16 > size || o15 > o16 {
return ssz.ErrOffset
}
// Field (17) 'justificationBits'
if cap(b.justificationBits) == 0 {
b.justificationBits = make([]byte, 0, len(buf[2687256:2687257]))
}
b.justificationBits = append(b.justificationBits, buf[2687256:2687257]...)
// Field (18) 'previousJustifiedCheckpoint'
if b.previousJustifiedCheckpoint == nil {
b.previousJustifiedCheckpoint = new(ethpb.Checkpoint)
}
if err = b.previousJustifiedCheckpoint.UnmarshalSSZ(buf[2687257:2687297]); err != nil {
return err
}
// Field (19) 'currentJustifiedCheckpoint'
if b.currentJustifiedCheckpoint == nil {
b.currentJustifiedCheckpoint = new(ethpb.Checkpoint)
}
if err = b.currentJustifiedCheckpoint.UnmarshalSSZ(buf[2687297:2687337]); err != nil {
return err
}
// Field (20) 'finalizedCheckpoint'
if b.finalizedCheckpoint == nil {
b.finalizedCheckpoint = new(ethpb.Checkpoint)
}
if err = b.finalizedCheckpoint.UnmarshalSSZ(buf[2687337:2687377]); err != nil {
return err
}
// Offset (21) 'inactivityScores'
if o21 = ssz.ReadOffset(buf[2687377:2687381]); o21 > size || o16 > o21 {
return ssz.ErrOffset
}
// Field (22) 'currentSyncCommittee'
if b.currentSyncCommittee == nil {
b.currentSyncCommittee = new(ethpb.SyncCommittee)
}
if err = b.currentSyncCommittee.UnmarshalSSZ(buf[2687381:2712005]); err != nil {
return err
}
// Field (23) 'nextSyncCommittee'
if b.nextSyncCommittee == nil {
b.nextSyncCommittee = new(ethpb.SyncCommittee)
}
if err = b.nextSyncCommittee.UnmarshalSSZ(buf[2712005:2736629]); err != nil {
return err
}
// Field (7) 'historicalRoots'
{
buf = tail[o7:o9]
num, err := ssz.DivideInt2(len(buf), 32, 16777216)
if err != nil {
return err
}
b.historicalRoots = make([][32]byte, num)
for ii := 0; ii < num; ii++ {
copy(b.historicalRoots[ii][:], buf[ii*32:(ii+1)*32])
}
}
// Field (9) 'eth1DataVotes'
{
buf = tail[o9:o11]
num, err := ssz.DivideInt2(len(buf), 72, 2048)
if err != nil {
return err
}
b.eth1DataVotes = make([]*ethpb.Eth1Data, num)
for ii := 0; ii < num; ii++ {
if b.eth1DataVotes[ii] == nil {
b.eth1DataVotes[ii] = new(ethpb.Eth1Data)
}
if err = b.eth1DataVotes[ii].UnmarshalSSZ(buf[ii*72 : (ii+1)*72]); err != nil {
return err
}
}
}
// Field (11) 'validators'
{
buf = tail[o11:o12]
num, err := ssz.DivideInt2(len(buf), 121, 1099511627776)
if err != nil {
return err
}
b.validators = make([]*ethpb.Validator, num)
for ii := 0; ii < num; ii++ {
if b.validators[ii] == nil {
b.validators[ii] = new(ethpb.Validator)
}
if err = b.validators[ii].UnmarshalSSZ(buf[ii*121 : (ii+1)*121]); err != nil {
return err
}
}
}
// Field (12) 'balances'
{
buf = tail[o12:o15]
num, err := ssz.DivideInt2(len(buf), 8, 1099511627776)
if err != nil {
return err
}
b.balances = ssz.ExtendUint64(b.balances, num)
for ii := 0; ii < num; ii++ {
b.balances[ii] = ssz.UnmarshallUint64(buf[ii*8 : (ii+1)*8])
}
}
// Field (15) 'previousEpochParticipation'
{
buf = tail[o15:o16]
if len(buf) > 1099511627776 {
return ssz.ErrBytesLength
}
if cap(b.previousEpochParticipation) == 0 {
b.previousEpochParticipation = make([]byte, 0, len(buf))
}
b.previousEpochParticipation = append(b.previousEpochParticipation, buf...)
}
// Field (16) 'currentEpochParticipation'
{
buf = tail[o16:o21]
if len(buf) > 1099511627776 {
return ssz.ErrBytesLength
}
if cap(b.currentEpochParticipation) == 0 {
b.currentEpochParticipation = make([]byte, 0, len(buf))
}
b.currentEpochParticipation = append(b.currentEpochParticipation, buf...)
}
// Field (21) 'inactivityScores'
{
buf = tail[o21:]
num, err := ssz.DivideInt2(len(buf), 8, 1099511627776)
if err != nil {
return err
}
b.inactivityScores = ssz.ExtendUint64(b.inactivityScores, num)
for ii := 0; ii < num; ii++ {
b.inactivityScores[ii] = ssz.UnmarshallUint64(buf[ii*8 : (ii+1)*8])
}
}
return err
}
// SizeSSZ returns the ssz encoded size in bytes for the BeaconState object
func (b *BeaconState) SizeSSZ() (size int) {
size = 2736629
// Field (7) 'historicalRoots'
size += len(b.historicalRoots) * 32
// Field (9) 'eth1DataVotes'
size += len(b.eth1DataVotes) * 72
// Field (11) 'validators'
size += len(b.validators) * 121
// Field (12) 'balances'
size += len(b.balances) * 8
// Field (15) 'previousEpochParticipation'
size += len(b.previousEpochParticipation)
// Field (16) 'currentEpochParticipation'
size += len(b.currentEpochParticipation)
// Field (21) 'inactivityScores'
size += len(b.inactivityScores) * 8
return
}

View File

@@ -1,47 +1,42 @@
package v2
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 := &ethpb.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
}

View File

@@ -30,9 +30,20 @@ func TestBeaconState_BlockRoots(t *testing.T) {
s, err := InitializeFromProto(&ethpb.BeaconStateAltair{})
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(&ethpb.BeaconStateAltair{BlockRoots: want})
require.NoError(t, err)
got = s.BlockRoots()
@@ -48,10 +59,15 @@ 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(&ethpb.BeaconStateAltair{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(&ethpb.BeaconStateAltair{BlockRoots: bRoots})
require.NoError(t, err)
got, err = s.BlockRootAtIndex(0)
require.NoError(t, err)

View File

@@ -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.
// 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
}

View File

@@ -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
}

View File

@@ -1,112 +1,25 @@
package v2
import (
"time"
types "github.com/prysmaticlabs/eth2-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/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, fieldparams.RootLength)
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
@@ -118,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 &ethpb.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)
}

View File

@@ -2,52 +2,40 @@ package v2
// 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
}

View File

@@ -1,67 +1,52 @@
package v2
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)
}

View File

@@ -1,118 +1,126 @@
package v2
import (
"fmt"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
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 &ethpb.BeaconStateAltair{
GenesisTime: b.genesisTime,
GenesisValidatorsRoot: gvrCopy[:],
Slot: b.slot,
Fork: b.fork,
LatestBlockHeader: b.latestBlockHeader,
BlockRoots: b.blockRoots.Slice(),
StateRoots: b.stateRoots.Slice(),
HistoricalRoots: b.historicalRoots.Slice(),
Eth1Data: b.eth1Data,
Eth1DataVotes: b.eth1DataVotes,
Eth1DepositIndex: b.eth1DepositIndex,
Validators: b.validators,
Balances: b.balances,
RandaoMixes: b.randaoMixes.Slice(),
Slashings: b.slashings,
PreviousEpochParticipation: b.previousEpochParticipation,
CurrentEpochParticipation: b.currentEpochParticipation,
JustificationBits: b.justificationBits,
PreviousJustifiedCheckpoint: b.previousJustifiedCheckpoint,
CurrentJustifiedCheckpoint: b.currentJustifiedCheckpoint,
FinalizedCheckpoint: b.finalizedCheckpoint,
InactivityScores: b.inactivityScores,
CurrentSyncCommittee: b.currentSyncCommittee,
NextSyncCommittee: b.nextSyncCommittee,
}
}
// 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 &ethpb.BeaconStateAltair{
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(),
}
}
// 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 &ethpb.BeaconStateAltair{
GenesisTime: b.genesisTime,
GenesisValidatorsRoot: gvrCopy[:],
Slot: b.slot,
Fork: b.forkVal(),
LatestBlockHeader: b.latestBlockHeaderVal(),
BlockRoots: b.blockRoots.Slice(),
StateRoots: b.stateRoots.Slice(),
HistoricalRoots: b.historicalRoots.Slice(),
Eth1Data: b.eth1DataVal(),
Eth1DataVotes: b.eth1DataVotesVal(),
Eth1DepositIndex: b.eth1DepositIndex,
Validators: b.validatorsVal(),
Balances: b.balancesVal(),
RandaoMixes: b.randaoMixes.Slice(),
Slashings: b.slashingsVal(),
PreviousEpochParticipation: b.previousEpochParticipationVal(),
CurrentEpochParticipation: b.currentEpochParticipationVal(),
JustificationBits: b.justificationBitsVal(),
PreviousJustifiedCheckpoint: b.previousJustifiedCheckpointVal(),
CurrentJustifiedCheckpoint: b.currentJustifiedCheckpointVal(),
FinalizedCheckpoint: b.finalizedCheckpointVal(),
InactivityScores: b.inactivityScoresVal(),
CurrentSyncCommittee: b.currentSyncCommitteeVal(),
NextSyncCommittee: b.nextSyncCommitteeVal(),
}
}
// StateRoots kept track of in the beacon state.
func (b *BeaconState) StateRoots() [][]byte {
if !b.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)
}
// 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()
return b.stateRoots[idx], nil
}
// ProtobufBeaconState transforms an input into beacon state hard fork 1 in the form of protobuf.
@@ -124,3 +132,14 @@ func ProtobufBeaconState(s interface{}) (*ethpb.BeaconStateAltair, error) {
}
return pbState, nil
}
// InnerStateUnsafe returns the pointer value of the underlying
// beacon state proto object, bypassing immutability. Use with care.
func (b *BeaconState) InnerStateUnsafe() interface{} {
return b.ToProtoUnsafe()
}
// CloneInnerState the beacon state into a protobuf for usage.
func (b *BeaconState) CloneInnerState() interface{} {
return b.ToProto()
}

View File

@@ -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.

View File

@@ -1,7 +1,6 @@
package v2
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{}
@@ -106,7 +45,7 @@ func TestBeaconState_ValidatorByPubkey(t *testing.T) {
}{
{
name: "retrieve validator",
modifyFunc: func(b *BeaconState, key [48]byte) {
modifyFunc: func(b *BeaconState, key [fieldparams.BLSPubkeyLength]byte) {
assert.NoError(t, b.AppendValidator(&ethpb.Validator{PublicKey: key[:]}))
},
exists: true,

View File

@@ -6,7 +6,7 @@ import (
"github.com/pkg/errors"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/v1"
v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
@@ -18,6 +18,12 @@ type ValidatorIndexOutOfRangeError struct {
message string
}
var (
// ErrNilValidatorsInState returns when accessing validators in the state while the state has a
// nil slice for the validators field.
ErrNilValidatorsInState = errors.New("state has nil validator slice")
)
// NewValidatorIndexOutOfRangeError creates a new error instance.
func NewValidatorIndexOutOfRangeError(index types.ValidatorIndex) ValidatorIndexOutOfRangeError {
return ValidatorIndexOutOfRangeError{
@@ -32,32 +38,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 +70,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 +88,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 &ethpb.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 +99,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.validators == nil {
return nil, ErrNilValidatorsInState
}
if b.state.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 +117,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 +127,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 +139,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 +183,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 +234,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
}

View File

@@ -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.

View File

@@ -4,7 +4,7 @@ import (
"context"
"testing"
v2 "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/v2"
v2 "github.com/prysmaticlabs/prysm/beacon-chain/state/v2"
"github.com/prysmaticlabs/prysm/container/trie"
"github.com/prysmaticlabs/prysm/crypto/bls"
"github.com/prysmaticlabs/prysm/testing/require"

View File

@@ -3,19 +3,18 @@ package v2
import (
"fmt"
customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
)
// SetLatestBlockHeader in the beacon state.
func (b *BeaconState) SetLatestBlockHeader(val *ethpb.BeaconBlockHeader) error {
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][32]byte
for i := 0; i < len(rootsArr); i++ {
copy(rootsArr[i][:], val[i])
}
roots := customtypes.BlockRoots(rootsArr)
b.blockRoots = &roots
b.markFieldAsDirty(blockRoots)
b.rebuildTrie[blockRoots] = true
return nil
@@ -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})

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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([][32]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([][32]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
}

View File

@@ -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
}

View File

@@ -2,22 +2,27 @@ package v2
import (
"github.com/pkg/errors"
customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
)
// SetRandaoMixes for the beacon state. Updates the entire
// randao mixes to a new value by overwriting the previous one.
func (b *BeaconState) SetRandaoMixes(val [][]byte) error {
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][32]byte
for i := 0; i < len(mixesArr); i++ {
copy(mixesArr[i][:], val[i])
}
mixes := customtypes.RandaoMixes(mixesArr)
b.randaoMixes = &mixes
b.markFieldAsDirty(randaoMixes)
b.rebuildTrie[randaoMixes] = true
return nil
@@ -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})

View File

@@ -2,22 +2,26 @@ package v2
import (
"github.com/pkg/errors"
customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
)
// SetStateRoots for the beacon state. Updates the state roots
// to a new value by overwriting the previous value.
func (b *BeaconState) SetStateRoots(val [][]byte) error {
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][32]byte
for i := 0; i < len(rootsArr); i++ {
copy(rootsArr[i][:], val[i])
}
roots := customtypes.StateRoots(rootsArr)
b.stateRoots = &roots
b.markFieldAsDirty(stateRoots)
b.rebuildTrie[stateRoots] = true
return nil
@@ -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})

View File

@@ -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
}

View File

@@ -8,67 +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[:]
}
st, err := InitializeFromProto(&ethpb.BeaconStateAltair{
Slot: 1,
CurrentEpochParticipation: []byte{},
PreviousEpochParticipation: []byte{},
Validators: []*ethpb.Validator{},
Eth1Data: &ethpb.Eth1Data{},
BlockRoots: mockblockRoots,
StateRoots: mockstateRoots,
RandaoMixes: mockrandaoMixes,
})
require.NoError(t, err)
_, err = st.HashTreeRoot(context.Background())
require.NoError(t, err)
for i := stateTypes.FieldIndex(0); i < stateTypes.FieldIndex(params.BeaconConfig().BeaconStateAltairFieldCount); 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(&ethpb.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(&ethpb.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)))
@@ -104,7 +56,7 @@ func TestBeaconState_AppendBalanceWithTrie(t *testing.T) {
}
st, err := InitializeFromProto(&ethpb.BeaconStateAltair{
Slot: 1,
GenesisValidatorsRoot: make([]byte, 32),
GenesisValidatorsRoot: make([]byte, fieldparams.RootLength),
Fork: &ethpb.Fork{
PreviousVersion: make([]byte, 4),
CurrentVersion: make([]byte, 4),
@@ -121,7 +73,7 @@ func TestBeaconState_AppendBalanceWithTrie(t *testing.T) {
Balances: bals,
Eth1Data: &ethpb.Eth1Data{
DepositRoot: make([]byte, fieldparams.RootLength),
BlockHash: make([]byte, 32),
BlockHash: make([]byte, fieldparams.RootLength),
},
BlockRoots: mockblockRoots,
StateRoots: mockstateRoots,
@@ -133,11 +85,11 @@ func TestBeaconState_AppendBalanceWithTrie(t *testing.T) {
Slashings: make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector),
CurrentSyncCommittee: &ethpb.SyncCommittee{
Pubkeys: pubKeys,
AggregatePubkey: make([]byte, 48),
AggregatePubkey: make([]byte, fieldparams.BLSPubkeyLength),
},
NextSyncCommittee: &ethpb.SyncCommittee{
Pubkeys: pubKeys,
AggregatePubkey: make([]byte, 48),
AggregatePubkey: make([]byte, fieldparams.BLSPubkeyLength),
},
})
assert.NoError(t, err)
@@ -155,7 +107,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")
}

View File

@@ -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.rebuildTrie[balances] = true
b.markFieldAsDirty(balances)
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
}

View File

@@ -9,7 +9,8 @@ import (
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/fieldtrie"
"github.com/prysmaticlabs/prysm/beacon-chain/state/fieldtrie"
customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
"github.com/prysmaticlabs/prysm/beacon-chain/state/types"
"github.com/prysmaticlabs/prysm/config/features"
@@ -50,16 +51,57 @@ func InitializeFromSSZBytes(marshaled []byte) (*BeaconState, error) {
return InitializeFromProtoUnsafe(st)
}
// 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.BeaconStateAltair) (*BeaconState, error) {
if st == nil {
return nil, errors.New("received nil state")
}
var bRoots customtypes.BlockRoots
for i, r := range st.BlockRoots {
bRoots[i] = bytesutil.ToBytes32(r)
}
var sRoots customtypes.StateRoots
for i, r := range st.StateRoots {
sRoots[i] = bytesutil.ToBytes32(r)
}
hRoots := customtypes.HistoricalRoots(make([][32]byte, len(st.HistoricalRoots)))
for i, r := range st.HistoricalRoots {
hRoots[i] = bytesutil.ToBytes32(r)
}
var mixes customtypes.RandaoMixes
for i, m := range st.RandaoMixes {
mixes[i] = bytesutil.ToBytes32(m)
}
fieldCount := params.BeaconConfig().BeaconStateAltairFieldCount
b := &BeaconState{
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,
dirtyFields: make(map[types.FieldIndex]bool, fieldCount),
dirtyIndices: make(map[types.FieldIndex][]uint64, fieldCount),
stateFieldLeaves: make(map[types.FieldIndex]*fieldtrie.FieldTrie, fieldCount),
@@ -98,48 +140,43 @@ func InitializeFromProtoUnsafe(st *ethpb.BeaconStateAltair) (*BeaconState, error
// 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().BeaconStateAltairFieldCount
dst := &BeaconState{
state: &ethpb.BeaconStateAltair{
// 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.
blockRoots: b.blockRoots,
stateRoots: b.stateRoots,
randaoMixes: b.randaoMixes,
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.
historicalRoots: b.historicalRoots,
balances: b.balances,
previousEpochParticipation: b.previousEpochParticipation,
currentEpochParticipation: b.currentEpochParticipation,
inactivityScores: b.inactivityScores,
validators: b.validators,
// Everything else, too small to be concerned about, constant size.
genesisValidatorsRoot: b.genesisValidatorsRoot,
justificationBits: b.justificationBitsVal(),
fork: b.forkVal(),
latestBlockHeader: b.latestBlockHeaderVal(),
eth1Data: b.eth1DataVal(),
previousJustifiedCheckpoint: b.previousJustifiedCheckpointVal(),
currentJustifiedCheckpoint: b.currentJustifiedCheckpointVal(),
finalizedCheckpoint: b.finalizedCheckpointVal(),
currentSyncCommittee: b.currentSyncCommitteeVal(),
nextSyncCommittee: b.nextSyncCommitteeVal(),
// 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(),
},
dirtyFields: make(map[types.FieldIndex]bool, fieldCount),
dirtyIndices: make(map[types.FieldIndex][]uint64, fieldCount),
rebuildTrie: make(map[types.FieldIndex]bool, fieldCount),
@@ -238,7 +275,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.BeaconStateAltair)
if !ok {
return errors.New("state is of the wrong type")
}
fieldRoots, err := computeFieldRoots(ctx, protoState)
if err != nil {
return err
}
@@ -286,7 +327,7 @@ 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(ctx context.Context, field types.FieldIndex) ([32]byte, error) {
@@ -297,46 +338,50 @@ func (b *BeaconState) rootSelector(ctx context.Context, field types.FieldIndex)
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
}
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
}
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 {
@@ -345,63 +390,63 @@ func (b *BeaconState) rootSelector(ctx context.Context, field types.FieldIndex)
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
}
delete(b.rebuildTrie, validators)
return b.stateFieldLeaves[field].TrieRoot()
}
return b.recomputeFieldTrie(validators, b.state.Validators)
return b.recomputeFieldTrie(validators, b.validators)
case balances:
if features.Get().EnableBalanceTrieComputation {
if b.rebuildTrie[field] {
maxBalCap := uint64(fieldparams.ValidatorRegistryLimit)
elemSize := uint64(8)
balLimit := (maxBalCap*elemSize + 31) / 32
err := b.resetFieldTrie(field, b.state.Balances, balLimit)
err := b.resetFieldTrie(field, b.balances, balLimit)
if err != nil {
return [32]byte{}, err
}
delete(b.rebuildTrie, field)
return b.stateFieldLeaves[field].TrieRoot()
}
return b.recomputeFieldTrie(balances, b.state.Balances)
return b.recomputeFieldTrie(balances, b.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
}
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)
}
return [32]byte{}, errors.New("invalid field index provided")
}

View File

@@ -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)))
@@ -120,7 +120,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()

View File

@@ -1,14 +1,8 @@
package v2
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() {
@@ -31,24 +25,6 @@ func init() {
// 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.BeaconStateAltair
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
}
// Field Aliases for values from the types package.
const (
genesisTime = types.GenesisTime

View File

@@ -147,7 +147,8 @@
"validator/.*": ""
},
"exclude_files": {
"beacon-chain/state/state-native/v1/generated.ssz.go": "Exclude generated SSZ file"
"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"
}
},
"properpermissions": {