Using the multi value slice for the beacon state (#12549)

* in progress...

* in progress...

* remove log

* log root

* Revert "Auxiliary commit to revert individual files from f12a609ea2a2f1e87e97321f3a717cd324b5ae97"

This reverts commit 5ae35edb6477d8d0ea4e94b273efc6590484da85.

* cleanup

* remove log

* remove whitespace

* remove logs

* more stuff

* copy

* always rebuild trie

* revert

* add state

* init state

* fix all

* uintptr

* move slice to new package

* lock in `Detach`

* remove constraint

* reorder

* blockroots and stateroots

* fill roots in empty()

* fix hasher

* implement slice for balances and inactivity scores

* detach in setters

* Revert "implement slice for balances and inactivity scores"

This reverts commit 59eb9df8d7.

# Conflicts:
#	beacon-chain/state/state-native/setters_validator.go

* use counter to track states

* typos

* rename interface

* balances

* gauge

* some improvements

* first try with map

* fix

* inactivity scores in progress

* fix test

# Conflicts:
#	beacon-chain/state/state-native/helpers_test.go

* test fixes

* ToProto fix

* copy roots

* validators

* build fixes

* fix bug in `ToProto`

* fix fuzz test

* fix bug in slice getters

* fix state equality checks

* make tests pass

* make tests pass

* more test updates

* Revert "Auxiliary commit to revert individual files from 34e7344bff08a589e6341bb1829e3cb74159e878"

This reverts commit ecd64efa8917f37ca41460e0356ff007fe55dd9d.

* Revert "make tests pass"

This reverts commit 0cf00f19ee.

* Revert "make tests pass"

This reverts commit 521b65e1d2.

* pass tests

* deepequal identifiable types

* Deflake `cloners_test.go`

* feature flag for block roots

* feature flag

* remove recursive locks

* reduce complexity of rootSelector

* fix randao mixes root

* some fixes

* revisit tests

* revert change to field trie helpers

* initialize field map for tests

* remove whitespace

* initialize roots with proper length

* more fixes

* out of bounds message fix

* optimize length calculation

* remove call to Len in PubkeyAtIndex

* don't log deposits

* unit tests

* unit tests

* fix

* comments

* test fixes

* id

* remove Enumerator interface

* review feedback

* simplify field trie

* bring back fieldtrie package

* fix bazel file

* use handle32ByteArrays for root computation

* fix locks

* metrics

* bzl

* simplify some things

* use htr in state test

* remove code from require package

* gzl

* more htr

* Fuzzing of the multi-value slice

* assert values

* getter optimizations

* use At when reading from validators

* Nishant's review

* restore safe copy

* remove empty line

* build fix

* restore how we get root at index for deafult mode

* more review comments

* optimize default behavior

* simplify Slice calls

* test fix

* remove unnecessary package

* remove unused setter

* make fieldMap unexported

* some improvements in state package

* call `Slice` instead of manually copying

* unlock in ReadFromEveryValidator

* Potuz's comments

* lock the state when reading from all validators

# Conflicts:
#	beacon-chain/state/state-native/getters_validator.go

* add back preston's changes

* add index

---------

Co-authored-by: Potuz <potuz@prysmaticlabs.com>
Co-authored-by: nisdas <nishdas93@gmail.com>
Co-authored-by: Preston Van Loon <pvanloon@offchainlabs.com>
This commit is contained in:
Radosław Kapka
2023-10-06 03:10:05 +02:00
committed by GitHub
parent de0c7e6256
commit 44973b0bb3
60 changed files with 1742 additions and 984 deletions

View File

@@ -16,7 +16,7 @@ func TestReportEpochMetrics_BadHeadState(t *testing.T) {
require.NoError(t, err)
require.NoError(t, h.SetValidators(nil))
err = reportEpochMetrics(context.Background(), s, h)
require.ErrorContains(t, "failed to initialize precompute: nil validators in state", err)
require.ErrorContains(t, "failed to initialize precompute: state has nil validator slice", err)
}
func TestReportEpochMetrics_BadAttestation(t *testing.T) {

View File

@@ -31,7 +31,7 @@ func Test_BaseReward(t *testing.T) {
valIdx: 2,
st: genState(1),
want: 0,
errString: "index 2 out of range",
errString: "validator index 2 does not exist",
},
{
name: "active balance is 32eth",
@@ -89,7 +89,7 @@ func Test_BaseRewardWithTotalBalance(t *testing.T) {
valIdx: 2,
activeBalance: 1,
want: 0,
errString: "index 2 out of range",
errString: "validator index 2 does not exist",
},
{
name: "active balance is 1",

View File

@@ -82,7 +82,7 @@ func ProcessRandaoNoVerify(
for i, x := range blockRandaoReveal {
latestMixSlice[i] ^= x
}
if err := beaconState.UpdateRandaoMixesAtIndex(uint64(currentEpoch%latestMixesLength), latestMixSlice); err != nil {
if err := beaconState.UpdateRandaoMixesAtIndex(uint64(currentEpoch%latestMixesLength), [32]byte(latestMixSlice)); err != nil {
return nil, err
}
return beaconState, nil

View File

@@ -152,7 +152,7 @@ func TestProcessBLSToExecutionChange(t *testing.T) {
}
_, err = blocks.ProcessBLSToExecutionChange(st, signed)
require.ErrorContains(t, "out of range", err)
require.ErrorContains(t, "out of bounds", err)
})
t.Run("signature does not verify", func(t *testing.T) {

View File

@@ -349,7 +349,7 @@ func ProcessRandaoMixesReset(state state.BeaconState) (state.BeaconState, error)
if err != nil {
return nil, err
}
if err := state.UpdateRandaoMixesAtIndex(uint64(nextEpoch%randaoMixLength), mix); err != nil {
if err := state.UpdateRandaoMixesAtIndex(uint64(nextEpoch%randaoMixLength), [32]byte(mix)); err != nil {
return nil, err
}

View File

@@ -99,7 +99,7 @@ func TestIsCurrentEpochSyncCommittee_DoesNotExist(t *testing.T) {
require.NoError(t, state.SetNextSyncCommittee(syncCommittee))
ok, err := IsCurrentPeriodSyncCommittee(state, 12390192)
require.ErrorContains(t, "index 12390192 out of range", err)
require.ErrorContains(t, "validator index 12390192 does not exist", err)
require.Equal(t, false, ok)
}
@@ -182,7 +182,7 @@ func TestIsNextEpochSyncCommittee_DoesNotExist(t *testing.T) {
require.NoError(t, state.SetNextSyncCommittee(syncCommittee))
ok, err := IsNextPeriodSyncCommittee(state, 120391029)
require.ErrorContains(t, "index 120391029 out of range", err)
require.ErrorContains(t, "validator index 120391029 does not exist", err)
require.Equal(t, false, ok)
}
@@ -282,7 +282,7 @@ func TestCurrentEpochSyncSubcommitteeIndices_DoesNotExist(t *testing.T) {
require.NoError(t, state.SetNextSyncCommittee(syncCommittee))
index, err := CurrentPeriodSyncSubcommitteeIndices(state, 129301923)
require.ErrorContains(t, "index 129301923 out of range", err)
require.ErrorContains(t, "validator index 129301923 does not exist", err)
require.DeepEqual(t, []primitives.CommitteeIndex(nil), index)
}
@@ -367,7 +367,7 @@ func TestNextEpochSyncSubcommitteeIndices_DoesNotExist(t *testing.T) {
require.NoError(t, state.SetNextSyncCommittee(syncCommittee))
index, err := NextPeriodSyncSubcommitteeIndices(state, 21093019)
require.ErrorContains(t, "index 21093019 out of range", err)
require.ErrorContains(t, "validator index 21093019 does not exist", err)
require.DeepEqual(t, []primitives.CommitteeIndex(nil), index)
}

View File

@@ -9,6 +9,7 @@ import (
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state"
state_native "github.com/prysmaticlabs/prysm/v4/beacon-chain/state/state-native"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state/stateutil"
fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams"
"github.com/prysmaticlabs/prysm/v4/config/params"
"github.com/prysmaticlabs/prysm/v4/container/trie"
ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
@@ -221,6 +222,18 @@ func OptimizedGenesisBeaconState(genesisTime uint64, preState state.BeaconState,
// EmptyGenesisState returns an empty beacon state object.
func EmptyGenesisState() (state.BeaconState, error) {
blockRoots := make([][]byte, fieldparams.BlockRootsLength)
for i := range blockRoots {
blockRoots[i] = make([]byte, fieldparams.RootLength)
}
stateRoots := make([][]byte, fieldparams.StateRootsLength)
for i := range stateRoots {
stateRoots[i] = make([]byte, fieldparams.RootLength)
}
mixes := make([][]byte, fieldparams.RandaoMixesLength)
for i := range mixes {
mixes[i] = make([]byte, fieldparams.RootLength)
}
st := &ethpb.BeaconState{
// Misc fields.
Slot: 0,
@@ -229,6 +242,9 @@ func EmptyGenesisState() (state.BeaconState, error) {
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
Epoch: 0,
},
BlockRoots: blockRoots,
StateRoots: stateRoots,
RandaoMixes: mixes,
// Validator registry fields.
Validators: []*ethpb.Validator{},
Balances: []uint64{},

View File

@@ -2,6 +2,7 @@ package beacon
import (
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
@@ -15,7 +16,7 @@ import (
"github.com/prysmaticlabs/prysm/v4/beacon-chain/core/transition"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/core"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/shared"
state_native "github.com/prysmaticlabs/prysm/v4/beacon-chain/state/state-native"
consensus_types "github.com/prysmaticlabs/prysm/v4/consensus-types"
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v4/crypto/bls"
http2 "github.com/prysmaticlabs/prysm/v4/network/http"
@@ -228,8 +229,8 @@ func (s *Server) SubmitVoluntaryExit(w http.ResponseWriter, r *http.Request) {
}
val, err := headState.ValidatorAtIndexReadOnly(exit.Exit.ValidatorIndex)
if err != nil {
if outOfRangeErr, ok := err.(*state_native.ValidatorIndexOutOfRangeError); ok {
http2.HandleError(w, "Could not get exiting validator: "+outOfRangeErr.Error(), http.StatusBadRequest)
if errors.Is(err, consensus_types.ErrOutOfBounds) {
http2.HandleError(w, "Could not get validator: "+err.Error(), http.StatusBadRequest)
return
}
http2.HandleError(w, "Could not get validator: "+err.Error(), http.StatusInternalServerError)

View File

@@ -485,7 +485,7 @@ func TestSubmitVoluntaryExit(t *testing.T) {
e := &http2.DefaultErrorJson{}
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e))
assert.Equal(t, http.StatusBadRequest, e.Code)
assert.Equal(t, true, strings.Contains(e.Message, "Could not get exiting validator"))
assert.Equal(t, true, strings.Contains(e.Message, "Could not get validator"))
})
}

View File

@@ -108,8 +108,8 @@ func TestGetStateRoot(t *testing.T) {
}
func TestGetRandao(t *testing.T) {
mixCurrent := bytesutil.PadTo([]byte("current"), 32)
mixOld := bytesutil.PadTo([]byte("old"), 32)
mixCurrent := bytesutil.ToBytes32([]byte("current"))
mixOld := bytesutil.ToBytes32([]byte("old"))
epochCurrent := primitives.Epoch(100000)
epochOld := 100000 - params.BeaconConfig().EpochsPerHistoricalVector + 1
@@ -125,7 +125,7 @@ func TestGetRandao(t *testing.T) {
headSt, err := util.NewBeaconState()
require.NoError(t, err)
require.NoError(t, headSt.SetSlot(params.BeaconConfig().SlotsPerEpoch))
headRandao := bytesutil.PadTo([]byte("head"), 32)
headRandao := bytesutil.ToBytes32([]byte("head"))
require.NoError(t, headSt.UpdateRandaoMixesAtIndex(uint64(headEpoch), headRandao))
db := dbTest.SetupDB(t)
@@ -143,17 +143,17 @@ func TestGetRandao(t *testing.T) {
t.Run("no epoch requested", func(t *testing.T) {
resp, err := server.GetRandao(ctx, &eth2.RandaoRequest{StateId: []byte("head")})
require.NoError(t, err)
assert.DeepEqual(t, mixCurrent, resp.Data.Randao)
assert.DeepEqual(t, mixCurrent[:], resp.Data.Randao)
})
t.Run("current epoch requested", func(t *testing.T) {
resp, err := server.GetRandao(ctx, &eth2.RandaoRequest{StateId: []byte("head"), Epoch: &epochCurrent})
require.NoError(t, err)
assert.DeepEqual(t, mixCurrent, resp.Data.Randao)
assert.DeepEqual(t, mixCurrent[:], resp.Data.Randao)
})
t.Run("old epoch requested", func(t *testing.T) {
resp, err := server.GetRandao(ctx, &eth2.RandaoRequest{StateId: []byte("head"), Epoch: &epochOld})
require.NoError(t, err)
assert.DeepEqual(t, mixOld, resp.Data.Randao)
assert.DeepEqual(t, mixOld[:], resp.Data.Randao)
})
t.Run("head state below `EpochsPerHistoricalVector`", func(t *testing.T) {
server.Stater = &testutil.MockStater{
@@ -161,7 +161,7 @@ func TestGetRandao(t *testing.T) {
}
resp, err := server.GetRandao(ctx, &eth2.RandaoRequest{StateId: []byte("head")})
require.NoError(t, err)
assert.DeepEqual(t, headRandao, resp.Data.Randao)
assert.DeepEqual(t, headRandao[:], resp.Data.Randao)
})
t.Run("epoch too old", func(t *testing.T) {
epochTooOld := primitives.Epoch(100000 - st.RandaoMixesLength())

View File

@@ -29,10 +29,10 @@ go_library(
"//beacon-chain/rpc/eth/shared:go_default_library",
"//beacon-chain/rpc/lookup:go_default_library",
"//beacon-chain/state:go_default_library",
"//beacon-chain/state/state-native:go_default_library",
"//beacon-chain/sync:go_default_library",
"//config/fieldparams:go_default_library",
"//config/params:go_default_library",
"//consensus-types:go_default_library",
"//consensus-types/primitives:go_default_library",
"//consensus-types/validator:go_default_library",
"//encoding/bytesutil:go_default_library",

View File

@@ -24,9 +24,9 @@ import (
rpchelpers "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/helpers"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/shared"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state"
state_native "github.com/prysmaticlabs/prysm/v4/beacon-chain/state/state-native"
fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams"
"github.com/prysmaticlabs/prysm/v4/config/params"
consensus_types "github.com/prysmaticlabs/prysm/v4/consensus-types"
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
validator2 "github.com/prysmaticlabs/prysm/v4/consensus-types/validator"
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
@@ -339,8 +339,8 @@ func (s *Server) SubmitBeaconCommitteeSubscription(w http.ResponseWriter, r *htt
subscriptions[i] = consensusItem
val, err := st.ValidatorAtIndexReadOnly(consensusItem.ValidatorIndex)
if err != nil {
if outOfRangeErr, ok := err.(*state_native.ValidatorIndexOutOfRangeError); ok {
http2.HandleError(w, "Could not get validator: "+outOfRangeErr.Error(), http.StatusBadRequest)
if errors.Is(err, consensus_types.ErrOutOfBounds) {
http2.HandleError(w, "Could not get validator: "+err.Error(), http.StatusBadRequest)
return
}
http2.HandleError(w, "Could not get validator: "+err.Error(), http.StatusInternalServerError)

View File

@@ -7,12 +7,11 @@ go_library(
"field_trie_helpers.go",
],
importpath = "github.com/prysmaticlabs/prysm/v4/beacon-chain/state/fieldtrie",
visibility = ["//beacon-chain:__subpackages__"],
visibility = ["//visibility:public"],
deps = [
"//beacon-chain/state/state-native/custom-types:go_default_library",
"//beacon-chain/state/state-native/types:go_default_library",
"//beacon-chain/state/stateutil:go_default_library",
"//encoding/bytesutil:go_default_library",
"//math:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"@com_github_pkg_errors//:go_default_library",

View File

@@ -31,11 +31,11 @@ type FieldTrie struct {
// NewFieldTrie is the constructor for the field trie data structure. It creates the corresponding
// trie according to the given parameters. Depending on whether the field is a basic/composite array
// which is either fixed/variable length, it will appropriately determine the trie.
func NewFieldTrie(field types.FieldIndex, dataType types.DataType, elements interface{}, length uint64) (*FieldTrie, error) {
func NewFieldTrie(field types.FieldIndex, fieldInfo types.DataType, elements interface{}, length uint64) (*FieldTrie, error) {
if elements == nil {
return &FieldTrie{
field: field,
dataType: dataType,
dataType: fieldInfo,
reference: stateutil.NewRef(1),
RWMutex: new(sync.RWMutex),
length: length,
@@ -48,10 +48,10 @@ func NewFieldTrie(field types.FieldIndex, dataType types.DataType, elements inte
return nil, err
}
if err := validateElements(field, dataType, elements, length); err != nil {
if err := validateElements(field, fieldInfo, elements, length); err != nil {
return nil, err
}
switch dataType {
switch fieldInfo {
case types.BasicArray:
fl, err := stateutil.ReturnTrieLayer(fieldRoots, length)
if err != nil {
@@ -60,7 +60,7 @@ func NewFieldTrie(field types.FieldIndex, dataType types.DataType, elements inte
return &FieldTrie{
fieldLayers: fl,
field: field,
dataType: dataType,
dataType: fieldInfo,
reference: stateutil.NewRef(1),
RWMutex: new(sync.RWMutex),
length: length,
@@ -70,14 +70,14 @@ func NewFieldTrie(field types.FieldIndex, dataType types.DataType, elements inte
return &FieldTrie{
fieldLayers: stateutil.ReturnTrieLayerVariable(fieldRoots, length),
field: field,
dataType: dataType,
dataType: fieldInfo,
reference: stateutil.NewRef(1),
RWMutex: new(sync.RWMutex),
length: length,
numOfElems: reflect.Indirect(reflect.ValueOf(elements)).Len(),
}, nil
default:
return nil, errors.Errorf("unrecognized data type in field map: %v", reflect.TypeOf(dataType).Name())
return nil, errors.Errorf("unrecognized data type in field map: %v", reflect.TypeOf(fieldInfo).Name())
}
}

View File

@@ -9,7 +9,6 @@ import (
customtypes "github.com/prysmaticlabs/prysm/v4/beacon-chain/state/state-native/custom-types"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state/state-native/types"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state/stateutil"
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
pmath "github.com/prysmaticlabs/prysm/v4/math"
ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
)
@@ -46,8 +45,8 @@ func (f *FieldTrie) validateIndices(idxs []uint64) error {
return nil
}
func validateElements(field types.FieldIndex, dataType types.DataType, elements interface{}, length uint64) error {
if dataType == types.CompressedArray {
func validateElements(field types.FieldIndex, fieldInfo types.DataType, elements interface{}, length uint64) error {
if fieldInfo == types.CompressedArray {
comLength, err := field.ElemsInChunk()
if err != nil {
return err
@@ -65,11 +64,11 @@ func validateElements(field types.FieldIndex, dataType types.DataType, elements
func fieldConverters(field types.FieldIndex, indices []uint64, elements interface{}, convertAll bool) ([][32]byte, error) {
switch field {
case types.BlockRoots:
return convertBlockRoots(indices, elements, convertAll)
return convert32ByteArrays[customtypes.BlockRoots](indices, elements, convertAll)
case types.StateRoots:
return convertStateRoots(indices, elements, convertAll)
return convert32ByteArrays[customtypes.StateRoots](indices, elements, convertAll)
case types.RandaoMixes:
return convertRandaoMixes(indices, elements, convertAll)
return convert32ByteArrays[customtypes.RandaoMixes](indices, elements, convertAll)
case types.Eth1DataVotes:
return convertEth1DataVotes(indices, elements, convertAll)
case types.Validators:
@@ -83,37 +82,13 @@ func fieldConverters(field types.FieldIndex, indices []uint64, elements interfac
}
}
func convertBlockRoots(indices []uint64, elements interface{}, convertAll bool) ([][32]byte, error) {
switch val := elements.(type) {
case [][]byte:
return handleByteArrays(val, indices, convertAll)
case *customtypes.BlockRoots:
return handle32ByteArrays(val[:], indices, convertAll)
default:
return nil, errors.Errorf("Incorrect type used for block roots")
}
}
func convertStateRoots(indices []uint64, elements interface{}, convertAll bool) ([][32]byte, error) {
switch val := elements.(type) {
case [][]byte:
return handleByteArrays(val, indices, convertAll)
case *customtypes.StateRoots:
return handle32ByteArrays(val[:], indices, convertAll)
default:
return nil, errors.Errorf("Incorrect type used for state roots")
}
}
func convertRandaoMixes(indices []uint64, elements interface{}, convertAll bool) ([][32]byte, error) {
switch val := elements.(type) {
case [][]byte:
return handleByteArrays(val, indices, convertAll)
case *customtypes.RandaoMixes:
return handle32ByteArrays(val[:], indices, convertAll)
default:
return nil, errors.Errorf("Incorrect type used for randao mixes")
func convert32ByteArrays[T ~[][32]byte](indices []uint64, elements interface{}, convertAll bool) ([][32]byte, error) {
val, ok := elements.(T)
if !ok {
var t T
return nil, errors.Errorf("Wanted type of %T but got %T", t, elements)
}
return handle32ByteArrays(val, indices, convertAll)
}
func convertEth1DataVotes(indices []uint64, elements interface{}, convertAll bool) ([][32]byte, error) {
@@ -148,34 +123,6 @@ func convertBalances(indices []uint64, elements interface{}, convertAll bool) ([
return handleBalanceSlice(val, indices, convertAll)
}
// handleByteArrays computes and returns byte arrays in a slice of root format.
func handleByteArrays(val [][]byte, indices []uint64, convertAll bool) ([][32]byte, error) {
length := len(indices)
if convertAll {
length = len(val)
}
roots := make([][32]byte, 0, length)
rootCreator := func(input []byte) {
newRoot := bytesutil.ToBytes32(input)
roots = append(roots, newRoot)
}
if convertAll {
for i := range val {
rootCreator(val[i])
}
return roots, nil
}
if len(val) > 0 {
for _, idx := range indices {
if idx > uint64(len(val))-1 {
return nil, fmt.Errorf("index %d greater than number of byte arrays %d", idx, len(val))
}
rootCreator(val[idx])
}
}
return roots, nil
}
// handle32ByteArrays computes and returns 32 byte arrays in a slice of root format.
func handle32ByteArrays(val [][32]byte, indices []uint64, convertAll bool) ([][32]byte, error) {
length := len(indices)

View File

@@ -4,6 +4,7 @@ import (
"testing"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state/fieldtrie"
customtypes "github.com/prysmaticlabs/prysm/v4/beacon-chain/state/state-native/custom-types"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state/state-native/types"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state/stateutil"
"github.com/prysmaticlabs/prysm/v4/config/params"
@@ -16,11 +17,15 @@ import (
func TestFieldTrie_NewTrie(t *testing.T) {
newState, _ := util.DeterministicGenesisState(t, 40)
roots := newState.BlockRoots()
blockRoots := make([][32]byte, len(roots))
for i, r := range roots {
blockRoots[i] = [32]byte(r)
}
// 5 represents the enum value of state roots
trie, err := fieldtrie.NewFieldTrie(types.FieldIndex(5), types.BasicArray, newState.StateRoots(), uint64(params.BeaconConfig().SlotsPerHistoricalRoot))
trie, err := fieldtrie.NewFieldTrie(types.BlockRoots, types.BasicArray, customtypes.BlockRoots(blockRoots), uint64(params.BeaconConfig().SlotsPerHistoricalRoot))
require.NoError(t, err)
root, err := stateutil.RootsArrayHashTreeRoot(newState.StateRoots(), uint64(params.BeaconConfig().SlotsPerHistoricalRoot))
root, err := stateutil.RootsArrayHashTreeRoot(newState.BlockRoots(), uint64(params.BeaconConfig().SlotsPerHistoricalRoot))
require.NoError(t, err)
newRoot, err := trie.TrieRoot()
require.NoError(t, err)
@@ -28,7 +33,7 @@ func TestFieldTrie_NewTrie(t *testing.T) {
}
func TestFieldTrie_NewTrie_NilElements(t *testing.T) {
trie, err := fieldtrie.NewFieldTrie(types.FieldIndex(5), types.BasicArray, nil, 8234)
trie, err := fieldtrie.NewFieldTrie(types.BlockRoots, types.BasicArray, nil, 8234)
require.NoError(t, err)
_, err = trie.TrieRoot()
require.ErrorIs(t, err, fieldtrie.ErrEmptyFieldTrie)
@@ -36,8 +41,7 @@ func TestFieldTrie_NewTrie_NilElements(t *testing.T) {
func TestFieldTrie_RecomputeTrie(t *testing.T) {
newState, _ := util.DeterministicGenesisState(t, 32)
// 10 represents the enum value of validators
trie, err := fieldtrie.NewFieldTrie(types.FieldIndex(11), types.CompositeArray, newState.Validators(), params.BeaconConfig().ValidatorRegistryLimit)
trie, err := fieldtrie.NewFieldTrie(types.Validators, types.CompositeArray, newState.Validators(), params.BeaconConfig().ValidatorRegistryLimit)
require.NoError(t, err)
oldroot, err := trie.TrieRoot()
@@ -68,7 +72,7 @@ func TestFieldTrie_RecomputeTrie(t *testing.T) {
func TestFieldTrie_RecomputeTrie_CompressedArray(t *testing.T) {
newState, _ := util.DeterministicGenesisState(t, 32)
trie, err := fieldtrie.NewFieldTrie(types.FieldIndex(12), types.CompressedArray, newState.Balances(), stateutil.ValidatorLimitForBalancesChunks())
trie, err := fieldtrie.NewFieldTrie(types.Balances, types.CompressedArray, newState.Balances(), stateutil.ValidatorLimitForBalancesChunks())
require.NoError(t, err)
require.Equal(t, trie.Length(), stateutil.ValidatorLimitForBalancesChunks())
changedIdx := []uint64{4, 8}
@@ -85,14 +89,19 @@ func TestFieldTrie_RecomputeTrie_CompressedArray(t *testing.T) {
func TestNewFieldTrie_UnknownType(t *testing.T) {
newState, _ := util.DeterministicGenesisState(t, 32)
_, err := fieldtrie.NewFieldTrie(types.FieldIndex(12), 4, newState.Balances(), 32)
_, err := fieldtrie.NewFieldTrie(types.Balances, 4, newState.Balances(), 32)
require.ErrorContains(t, "unrecognized data type", err)
}
func TestFieldTrie_CopyTrieImmutable(t *testing.T) {
newState, _ := util.DeterministicGenesisState(t, 32)
// 12 represents the enum value of randao mixes.
trie, err := fieldtrie.NewFieldTrie(types.FieldIndex(13), types.BasicArray, newState.RandaoMixes(), uint64(params.BeaconConfig().EpochsPerHistoricalVector))
mixes := newState.RandaoMixes()
randaoMixes := make([][32]byte, len(mixes))
for i, r := range mixes {
randaoMixes[i] = [32]byte(r)
}
trie, err := fieldtrie.NewFieldTrie(types.RandaoMixes, types.BasicArray, customtypes.RandaoMixes(randaoMixes), uint64(params.BeaconConfig().EpochsPerHistoricalVector))
require.NoError(t, err)
newTrie := trie.CopyTrie()
@@ -100,10 +109,15 @@ func TestFieldTrie_CopyTrieImmutable(t *testing.T) {
changedIdx := []uint64{2, 29}
changedVals := [][32]byte{{'A', 'B'}, {'C', 'D'}}
require.NoError(t, newState.UpdateRandaoMixesAtIndex(changedIdx[0], changedVals[0][:]))
require.NoError(t, newState.UpdateRandaoMixesAtIndex(changedIdx[1], changedVals[1][:]))
require.NoError(t, newState.UpdateRandaoMixesAtIndex(changedIdx[0], changedVals[0]))
require.NoError(t, newState.UpdateRandaoMixesAtIndex(changedIdx[1], changedVals[1]))
root, err := trie.RecomputeTrie(changedIdx, newState.RandaoMixes())
mixes = newState.RandaoMixes()
randaoMixes = make([][32]byte, len(mixes))
for i, r := range mixes {
randaoMixes[i] = [32]byte(r)
}
root, err := trie.RecomputeTrie(changedIdx, customtypes.RandaoMixes(randaoMixes))
require.NoError(t, err)
newRoot, err := newTrie.TrieRoot()
require.NoError(t, err)
@@ -113,7 +127,7 @@ func TestFieldTrie_CopyTrieImmutable(t *testing.T) {
}
func TestFieldTrie_CopyAndTransferEmpty(t *testing.T) {
trie, err := fieldtrie.NewFieldTrie(types.FieldIndex(13), types.BasicArray, nil, uint64(params.BeaconConfig().EpochsPerHistoricalVector))
trie, err := fieldtrie.NewFieldTrie(types.RandaoMixes, types.BasicArray, nil, uint64(params.BeaconConfig().EpochsPerHistoricalVector))
require.NoError(t, err)
require.DeepEqual(t, trie, trie.CopyTrie())
@@ -123,7 +137,7 @@ func TestFieldTrie_CopyAndTransferEmpty(t *testing.T) {
func TestFieldTrie_TransferTrie(t *testing.T) {
newState, _ := util.DeterministicGenesisState(t, 32)
maxLength := (params.BeaconConfig().ValidatorRegistryLimit*8 + 31) / 32
trie, err := fieldtrie.NewFieldTrie(types.FieldIndex(12), types.CompressedArray, newState.Balances(), maxLength)
trie, err := fieldtrie.NewFieldTrie(types.Balances, types.CompressedArray, newState.Balances(), maxLength)
require.NoError(t, err)
oldRoot, err := trie.TrieRoot()
require.NoError(t, err)

View File

@@ -103,22 +103,12 @@ func TestFieldTrie_NativeState_fieldConvertersNative(t *testing.T) {
errMsg string
expectedLength int
}{
{
name: "BlockRoots [][]bytes",
args: &args{
field: types.FieldIndex(5),
indices: []uint64{},
elements: [][]byte{[]byte("dfsadfsadf")},
convertAll: true,
},
wantHex: []string{"0x6466736164667361646600000000000000000000000000000000000000000000"},
},
{
name: "BlockRoots customtypes.BlockRoots",
args: &args{
field: types.FieldIndex(5),
indices: []uint64{},
elements: &customtypes.BlockRoots{},
elements: customtypes.BlockRoots{},
convertAll: true,
},
wantHex: []string{"0x0000000000000000000000000000000000000000000000000000000000000000"},
@@ -133,34 +123,14 @@ func TestFieldTrie_NativeState_fieldConvertersNative(t *testing.T) {
convertAll: true,
},
wantHex: nil,
errMsg: "Incorrect type used for block roots",
},
{
name: "BlockRoots [][]bytes",
args: &args{
field: types.FieldIndex(5),
indices: []uint64{},
elements: [][]byte{[]byte("dfsadfsadf")},
convertAll: true,
},
wantHex: []string{"0x6466736164667361646600000000000000000000000000000000000000000000"},
},
{
name: "StateRoots [][]bytes",
args: &args{
field: types.FieldIndex(6),
indices: []uint64{},
elements: [][]byte{[]byte("dfsadfsadf")},
convertAll: true,
},
wantHex: []string{"0x6466736164667361646600000000000000000000000000000000000000000000"},
errMsg: "Wanted type of customtypes.BlockRoots",
},
{
name: "StateRoots customtypes.StateRoots",
args: &args{
field: types.FieldIndex(6),
indices: []uint64{},
elements: &customtypes.StateRoots{},
elements: customtypes.StateRoots{},
convertAll: true,
},
wantHex: []string{"0x0000000000000000000000000000000000000000000000000000000000000000"},
@@ -175,45 +145,25 @@ func TestFieldTrie_NativeState_fieldConvertersNative(t *testing.T) {
convertAll: true,
},
wantHex: nil,
errMsg: "Incorrect type used for state roots",
},
{
name: "StateRoots [][]bytes convert all false",
args: &args{
field: types.FieldIndex(6),
indices: []uint64{},
elements: [][]byte{[]byte("dfsadfsadf")},
convertAll: false,
},
wantHex: []string{"0x6466736164667361646600000000000000000000000000000000000000000000"},
errMsg: "Wanted type of customtypes.StateRoots",
},
{
name: "StateRoots customtypes.StateRoots convert all false",
args: &args{
field: types.FieldIndex(6),
indices: []uint64{},
elements: &customtypes.StateRoots{},
elements: customtypes.StateRoots{},
convertAll: false,
},
wantHex: []string{"0x0000000000000000000000000000000000000000000000000000000000000000"},
expectedLength: 8192,
},
{
name: "RandaoMixes [][]bytes",
args: &args{
field: types.FieldIndex(13),
indices: []uint64{},
elements: [][]byte{[]byte("dfsadfsadf")},
convertAll: true,
},
wantHex: []string{"0x6466736164667361646600000000000000000000000000000000000000000000"},
},
{
name: "RandaoMixes customtypes.RandaoMixes",
args: &args{
field: types.FieldIndex(13),
indices: []uint64{},
elements: &customtypes.RandaoMixes{},
elements: customtypes.RandaoMixes{},
convertAll: true,
},
wantHex: []string{"0x0000000000000000000000000000000000000000000000000000000000000000"},
@@ -228,7 +178,7 @@ func TestFieldTrie_NativeState_fieldConvertersNative(t *testing.T) {
convertAll: true,
},
wantHex: nil,
errMsg: "Incorrect type used for randao mixes",
errMsg: "Wanted type of customtypes.RandaoMixes",
},
{
name: "Eth1DataVotes type not found",

View File

@@ -237,7 +237,7 @@ type WriteOnlyBalances interface {
// WriteOnlyRandaoMixes defines a struct which only has write access to randao mixes methods.
type WriteOnlyRandaoMixes interface {
SetRandaoMixes(val [][]byte) error
UpdateRandaoMixesAtIndex(idx uint64, val []byte) error
UpdateRandaoMixesAtIndex(idx uint64, val [32]byte) error
}
// WriteOnlyCheckpoint defines a struct which only has write access to check point methods.

View File

@@ -18,6 +18,7 @@ go_library(
"getters_validator.go",
"getters_withdrawal.go",
"hasher.go",
"multi_value_slices.go",
"proofs.go",
"readonly_validator.go",
"setters_attestation.go",
@@ -49,11 +50,14 @@ go_library(
"//beacon-chain/state/state-native/custom-types:go_default_library",
"//beacon-chain/state/state-native/types:go_default_library",
"//beacon-chain/state/stateutil:go_default_library",
"//config/features:go_default_library",
"//config/fieldparams:go_default_library",
"//config/params:go_default_library",
"//consensus-types:go_default_library",
"//consensus-types/blocks:go_default_library",
"//consensus-types/interfaces:go_default_library",
"//consensus-types/primitives:go_default_library",
"//container/multi-value-slice:go_default_library",
"//container/slice:go_default_library",
"//crypto/hash:go_default_library",
"//encoding/bytesutil:go_default_library",
@@ -64,6 +68,8 @@ go_library(
"//runtime/version:go_default_library",
"//time/slots:go_default_library",
"@com_github_pkg_errors//:go_default_library",
"@com_github_prometheus_client_golang//prometheus:go_default_library",
"@com_github_prometheus_client_golang//prometheus/promauto:go_default_library",
"@com_github_prysmaticlabs_fastssz//:go_default_library",
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
"@io_opencensus_go//trace:go_default_library",
@@ -82,6 +88,7 @@ go_test(
"getters_validator_test.go",
"getters_withdrawal_test.go",
"hasher_test.go",
"mvslice_fuzz_test.go",
"proofs_test.go",
"readonly_validator_test.go",
"references_test.go",
@@ -96,6 +103,7 @@ go_test(
"state_trie_test.go",
"types_test.go",
],
data = glob(["testdata/**"]),
embed = [":go_default_library"],
deps = [
"//beacon-chain/core/transition:go_default_library",
@@ -103,6 +111,7 @@ go_test(
"//beacon-chain/state/state-native/types:go_default_library",
"//beacon-chain/state/stateutil:go_default_library",
"//beacon-chain/state/testing:go_default_library",
"//config/features:go_default_library",
"//config/fieldparams:go_default_library",
"//config/params:go_default_library",
"//consensus-types/blocks:go_default_library",

View File

@@ -11,6 +11,7 @@ import (
customtypes "github.com/prysmaticlabs/prysm/v4/beacon-chain/state/state-native/custom-types"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state/state-native/types"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state/stateutil"
"github.com/prysmaticlabs/prysm/v4/config/features"
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
enginev1 "github.com/prysmaticlabs/prysm/v4/proto/engine/v1"
ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
@@ -25,16 +26,21 @@ type BeaconState struct {
slot primitives.Slot
fork *ethpb.Fork
latestBlockHeader *ethpb.BeaconBlockHeader
blockRoots *customtypes.BlockRoots
stateRoots *customtypes.StateRoots
blockRoots customtypes.BlockRoots
blockRootsMultiValue *MultiValueBlockRoots
stateRoots customtypes.StateRoots
stateRootsMultiValue *MultiValueStateRoots
historicalRoots customtypes.HistoricalRoots
historicalSummaries []*ethpb.HistoricalSummary
eth1Data *ethpb.Eth1Data
eth1DataVotes []*ethpb.Eth1Data
eth1DepositIndex uint64
validators []*ethpb.Validator
validatorsMultiValue *MultiValueValidators
balances []uint64
randaoMixes *customtypes.RandaoMixes
balancesMultiValue *MultiValueBalances
randaoMixes customtypes.RandaoMixes
randaoMixesMultiValue *MultiValueRandaoMixes
slashings []uint64
previousEpochAttestations []*ethpb.PendingAttestation
currentEpochAttestations []*ethpb.PendingAttestation
@@ -45,6 +51,7 @@ type BeaconState struct {
currentJustifiedCheckpoint *ethpb.Checkpoint
finalizedCheckpoint *ethpb.Checkpoint
inactivityScores []uint64
inactivityScoresMultiValue *MultiValueInactivityScores
currentSyncCommittee *ethpb.SyncCommittee
nextSyncCommittee *ethpb.SyncCommittee
latestExecutionPayloadHeader *enginev1.ExecutionPayloadHeader
@@ -53,6 +60,7 @@ type BeaconState struct {
nextWithdrawalIndex uint64
nextWithdrawalValidatorIndex primitives.ValidatorIndex
id uint64
lock sync.RWMutex
dirtyFields map[types.FieldIndex]bool
dirtyIndices map[types.FieldIndex][]uint64
@@ -70,8 +78,8 @@ type beaconStateMarshalable struct {
Slot primitives.Slot `json:"slot" yaml:"slot"`
Fork *ethpb.Fork `json:"fork" yaml:"fork"`
LatestBlockHeader *ethpb.BeaconBlockHeader `json:"latest_block_header" yaml:"latest_block_header"`
BlockRoots *customtypes.BlockRoots `json:"block_roots" yaml:"block_roots"`
StateRoots *customtypes.StateRoots `json:"state_roots" yaml:"state_roots"`
BlockRoots customtypes.BlockRoots `json:"block_roots" yaml:"block_roots"`
StateRoots customtypes.StateRoots `json:"state_roots" yaml:"state_roots"`
HistoricalRoots customtypes.HistoricalRoots `json:"historical_roots" yaml:"historical_roots"`
HistoricalSummaries []*ethpb.HistoricalSummary `json:"historical_summaries" yaml:"historical_summaries"`
Eth1Data *ethpb.Eth1Data `json:"eth_1_data" yaml:"eth_1_data"`
@@ -79,7 +87,7 @@ type beaconStateMarshalable struct {
Eth1DepositIndex uint64 `json:"eth_1_deposit_index" yaml:"eth_1_deposit_index"`
Validators []*ethpb.Validator `json:"validators" yaml:"validators"`
Balances []uint64 `json:"balances" yaml:"balances"`
RandaoMixes *customtypes.RandaoMixes `json:"randao_mixes" yaml:"randao_mixes"`
RandaoMixes customtypes.RandaoMixes `json:"randao_mixes" yaml:"randao_mixes"`
Slashings []uint64 `json:"slashings" yaml:"slashings"`
PreviousEpochAttestations []*ethpb.PendingAttestation `json:"previous_epoch_attestations" yaml:"previous_epoch_attestations"`
CurrentEpochAttestations []*ethpb.PendingAttestation `json:"current_epoch_attestations" yaml:"current_epoch_attestations"`
@@ -99,6 +107,29 @@ type beaconStateMarshalable struct {
}
func (b *BeaconState) MarshalJSON() ([]byte, error) {
var bRoots customtypes.BlockRoots
var sRoots customtypes.StateRoots
var mixes customtypes.RandaoMixes
var balances []uint64
var inactivityScores []uint64
var vals []*ethpb.Validator
if features.Get().EnableExperimentalState {
bRoots = b.blockRootsMultiValue.Value(b)
sRoots = b.stateRootsMultiValue.Value(b)
mixes = b.randaoMixesMultiValue.Value(b)
balances = b.balancesMultiValue.Value(b)
inactivityScores = b.inactivityScoresMultiValue.Value(b)
vals = b.validatorsMultiValue.Value(b)
} else {
bRoots = b.blockRoots
sRoots = b.stateRoots
mixes = b.randaoMixes
balances = b.balances
inactivityScores = b.inactivityScores
vals = b.validators
}
marshalable := &beaconStateMarshalable{
Version: b.version,
GenesisTime: b.genesisTime,
@@ -106,16 +137,16 @@ func (b *BeaconState) MarshalJSON() ([]byte, error) {
Slot: b.slot,
Fork: b.fork,
LatestBlockHeader: b.latestBlockHeader,
BlockRoots: b.blockRoots,
StateRoots: b.stateRoots,
BlockRoots: bRoots,
StateRoots: sRoots,
HistoricalRoots: b.historicalRoots,
HistoricalSummaries: b.historicalSummaries,
Eth1Data: b.eth1Data,
Eth1DataVotes: b.eth1DataVotes,
Eth1DepositIndex: b.eth1DepositIndex,
Validators: b.validators,
Balances: b.balances,
RandaoMixes: b.randaoMixes,
Validators: vals,
Balances: balances,
RandaoMixes: mixes,
Slashings: b.slashings,
PreviousEpochAttestations: b.previousEpochAttestations,
CurrentEpochAttestations: b.currentEpochAttestations,
@@ -125,7 +156,7 @@ func (b *BeaconState) MarshalJSON() ([]byte, error) {
PreviousJustifiedCheckpoint: b.previousJustifiedCheckpoint,
CurrentJustifiedCheckpoint: b.currentJustifiedCheckpoint,
FinalizedCheckpoint: b.finalizedCheckpoint,
InactivityScores: b.inactivityScores,
InactivityScores: inactivityScores,
CurrentSyncCommittee: b.currentSyncCommittee,
NextSyncCommittee: b.nextSyncCommittee,
LatestExecutionPayloadHeader: b.latestExecutionPayloadHeader,

View File

@@ -11,6 +11,7 @@ import (
customtypes "github.com/prysmaticlabs/prysm/v4/beacon-chain/state/state-native/custom-types"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state/state-native/types"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state/stateutil"
"github.com/prysmaticlabs/prysm/v4/config/features"
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
enginev1 "github.com/prysmaticlabs/prysm/v4/proto/engine/v1"
ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
@@ -25,16 +26,21 @@ type BeaconState struct {
slot primitives.Slot
fork *ethpb.Fork
latestBlockHeader *ethpb.BeaconBlockHeader
blockRoots *customtypes.BlockRoots
stateRoots *customtypes.StateRoots
blockRoots customtypes.BlockRoots
blockRootsMultiValue *MultiValueBlockRoots
stateRoots customtypes.StateRoots
stateRootsMultiValue *MultiValueStateRoots
historicalRoots customtypes.HistoricalRoots
historicalSummaries []*ethpb.HistoricalSummary
eth1Data *ethpb.Eth1Data
eth1DataVotes []*ethpb.Eth1Data
eth1DepositIndex uint64
validators []*ethpb.Validator
validatorsMultiValue *MultiValueValidators
balances []uint64
randaoMixes *customtypes.RandaoMixes
balancesMultiValue *MultiValueBalances
randaoMixes customtypes.RandaoMixes
randaoMixesMultiValue *MultiValueRandaoMixes
slashings []uint64
previousEpochAttestations []*ethpb.PendingAttestation
currentEpochAttestations []*ethpb.PendingAttestation
@@ -45,6 +51,7 @@ type BeaconState struct {
currentJustifiedCheckpoint *ethpb.Checkpoint
finalizedCheckpoint *ethpb.Checkpoint
inactivityScores []uint64
inactivityScoresMultiValue *MultiValueInactivityScores
currentSyncCommittee *ethpb.SyncCommittee
nextSyncCommittee *ethpb.SyncCommittee
latestExecutionPayloadHeader *enginev1.ExecutionPayloadHeader
@@ -53,6 +60,7 @@ type BeaconState struct {
nextWithdrawalIndex uint64
nextWithdrawalValidatorIndex primitives.ValidatorIndex
id uint64
lock sync.RWMutex
dirtyFields map[types.FieldIndex]bool
dirtyIndices map[types.FieldIndex][]uint64
@@ -70,8 +78,8 @@ type beaconStateMarshalable struct {
Slot primitives.Slot `json:"slot" yaml:"slot"`
Fork *ethpb.Fork `json:"fork" yaml:"fork"`
LatestBlockHeader *ethpb.BeaconBlockHeader `json:"latest_block_header" yaml:"latest_block_header"`
BlockRoots *customtypes.BlockRoots `json:"block_roots" yaml:"block_roots"`
StateRoots *customtypes.StateRoots `json:"state_roots" yaml:"state_roots"`
BlockRoots customtypes.BlockRoots `json:"block_roots" yaml:"block_roots"`
StateRoots customtypes.StateRoots `json:"state_roots" yaml:"state_roots"`
HistoricalRoots customtypes.HistoricalRoots `json:"historical_roots" yaml:"historical_roots"`
HistoricalSummaries []*ethpb.HistoricalSummary `json:"historical_summaries" yaml:"historical_summaries"`
Eth1Data *ethpb.Eth1Data `json:"eth_1_data" yaml:"eth_1_data"`
@@ -79,7 +87,7 @@ type beaconStateMarshalable struct {
Eth1DepositIndex uint64 `json:"eth_1_deposit_index" yaml:"eth_1_deposit_index"`
Validators []*ethpb.Validator `json:"validators" yaml:"validators"`
Balances []uint64 `json:"balances" yaml:"balances"`
RandaoMixes *customtypes.RandaoMixes `json:"randao_mixes" yaml:"randao_mixes"`
RandaoMixes customtypes.RandaoMixes `json:"randao_mixes" yaml:"randao_mixes"`
Slashings []uint64 `json:"slashings" yaml:"slashings"`
PreviousEpochAttestations []*ethpb.PendingAttestation `json:"previous_epoch_attestations" yaml:"previous_epoch_attestations"`
CurrentEpochAttestations []*ethpb.PendingAttestation `json:"current_epoch_attestations" yaml:"current_epoch_attestations"`
@@ -99,6 +107,29 @@ type beaconStateMarshalable struct {
}
func (b *BeaconState) MarshalJSON() ([]byte, error) {
var bRoots customtypes.BlockRoots
var sRoots customtypes.StateRoots
var mixes customtypes.RandaoMixes
var balances []uint64
var inactivityScores []uint64
var vals []*ethpb.Validator
if features.Get().EnableExperimentalState {
bRoots = b.blockRootsMultiValue.Value(b)
sRoots = b.stateRootsMultiValue.Value(b)
mixes = b.randaoMixesMultiValue.Value(b)
balances = b.balancesMultiValue.Value(b)
inactivityScores = b.inactivityScoresMultiValue.Value(b)
vals = b.validatorsMultiValue.Value(b)
} else {
bRoots = b.blockRoots
sRoots = b.stateRoots
mixes = b.randaoMixes
balances = b.balances
inactivityScores = b.inactivityScores
vals = b.validators
}
marshalable := &beaconStateMarshalable{
Version: b.version,
GenesisTime: b.genesisTime,
@@ -106,16 +137,16 @@ func (b *BeaconState) MarshalJSON() ([]byte, error) {
Slot: b.slot,
Fork: b.fork,
LatestBlockHeader: b.latestBlockHeader,
BlockRoots: b.blockRoots,
StateRoots: b.stateRoots,
BlockRoots: bRoots,
StateRoots: sRoots,
HistoricalRoots: b.historicalRoots,
HistoricalSummaries: b.historicalSummaries,
Eth1Data: b.eth1Data,
Eth1DataVotes: b.eth1DataVotes,
Eth1DepositIndex: b.eth1DepositIndex,
Validators: b.validators,
Balances: b.balances,
RandaoMixes: b.randaoMixes,
Validators: vals,
Balances: balances,
RandaoMixes: mixes,
Slashings: b.slashings,
PreviousEpochAttestations: b.previousEpochAttestations,
CurrentEpochAttestations: b.currentEpochAttestations,
@@ -125,7 +156,7 @@ func (b *BeaconState) MarshalJSON() ([]byte, error) {
PreviousJustifiedCheckpoint: b.previousJustifiedCheckpoint,
CurrentJustifiedCheckpoint: b.currentJustifiedCheckpoint,
FinalizedCheckpoint: b.finalizedCheckpoint,
InactivityScores: b.inactivityScores,
InactivityScores: inactivityScores,
CurrentSyncCommittee: b.currentSyncCommittee,
NextSyncCommittee: b.nextSyncCommittee,
LatestExecutionPayloadHeader: b.latestExecutionPayloadHeader,

View File

@@ -7,12 +7,12 @@ import (
fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams"
)
var _ fssz.HashRoot = (BlockRoots)([fieldparams.BlockRootsLength][32]byte{})
var _ fssz.HashRoot = (BlockRoots)([][32]byte{})
var _ fssz.Marshaler = (*BlockRoots)(nil)
var _ fssz.Unmarshaler = (*BlockRoots)(nil)
// BlockRoots represents block roots of the beacon state.
type BlockRoots [fieldparams.BlockRootsLength][32]byte
type BlockRoots [][32]byte
// HashTreeRoot returns calculated hash root.
func (r BlockRoots) HashTreeRoot() ([32]byte, error) {
@@ -35,7 +35,7 @@ func (r *BlockRoots) UnmarshalSSZ(buf []byte) error {
return fmt.Errorf("expected buffer of length %d received %d", r.SizeSSZ(), len(buf))
}
var roots BlockRoots
roots := BlockRoots(make([][32]byte, fieldparams.BlockRootsLength))
for i := range roots {
copy(roots[i][:], buf[i*32:(i+1)*32])
}
@@ -44,7 +44,7 @@ func (r *BlockRoots) UnmarshalSSZ(buf []byte) error {
}
// MarshalSSZTo marshals BlockRoots with the provided byte slice.
func (r *BlockRoots) MarshalSSZTo(dst []byte) ([]byte, error) {
func (r BlockRoots) MarshalSSZTo(dst []byte) ([]byte, error) {
marshalled, err := r.MarshalSSZ()
if err != nil {
return nil, err
@@ -53,7 +53,7 @@ func (r *BlockRoots) MarshalSSZTo(dst []byte) ([]byte, error) {
}
// MarshalSSZ marshals BlockRoots into a serialized object.
func (r *BlockRoots) MarshalSSZ() ([]byte, error) {
func (r BlockRoots) MarshalSSZ() ([]byte, error) {
marshalled := make([]byte, fieldparams.BlockRootsLength*32)
for i, r32 := range r {
for j, rr := range r32 {
@@ -64,12 +64,13 @@ func (r *BlockRoots) MarshalSSZ() ([]byte, error) {
}
// SizeSSZ returns the size of the serialized object.
func (_ *BlockRoots) SizeSSZ() int {
func (_ BlockRoots) SizeSSZ() int {
return fieldparams.BlockRootsLength * 32
}
// Slice converts a customtypes.BlockRoots object into a 2D byte slice.
func (r *BlockRoots) Slice() [][]byte {
// Each item in the slice is a copy of the original item.
func (r BlockRoots) Slice() [][]byte {
if r == nil {
return nil
}

View File

@@ -8,14 +8,6 @@ import (
"github.com/prysmaticlabs/prysm/v4/testing/assert"
)
func TestBlockRoots_Casting(t *testing.T) {
var b [fieldparams.BlockRootsLength][32]byte
d := BlockRoots(b)
if !reflect.DeepEqual([fieldparams.BlockRootsLength][32]byte(d), b) {
t.Errorf("Unequal: %v = %v", d, b)
}
}
func TestBlockRoots_UnmarshalSSZ(t *testing.T) {
t.Run("Ok", func(t *testing.T) {
d := BlockRoots{}
@@ -70,7 +62,7 @@ func TestBlockRoots_MarshalSSZTo(t *testing.T) {
}
func TestBlockRoots_MarshalSSZ(t *testing.T) {
d := BlockRoots{}
d := BlockRoots(make([][32]byte, fieldparams.BlockRootsLength))
d[0] = [32]byte{'f', 'o', 'o'}
d[1] = [32]byte{'b', 'a', 'r'}
b, err := d.MarshalSSZ()
@@ -94,7 +86,7 @@ func TestBlockRoots_SizeSSZ(t *testing.T) {
func TestBlockRoots_Slice(t *testing.T) {
a, b, c := [32]byte{'a'}, [32]byte{'b'}, [32]byte{'c'}
roots := BlockRoots{}
roots := BlockRoots(make([][32]byte, fieldparams.BlockRootsLength))
roots[1] = a
roots[10] = b
roots[100] = c

View File

@@ -43,7 +43,7 @@ func (r *HistoricalRoots) UnmarshalSSZ(buf []byte) error {
}
// MarshalSSZTo marshals HistoricalRoots with the provided byte slice.
func (r *HistoricalRoots) MarshalSSZTo(dst []byte) ([]byte, error) {
func (r HistoricalRoots) MarshalSSZTo(dst []byte) ([]byte, error) {
marshalled, err := r.MarshalSSZ()
if err != nil {
return nil, err
@@ -52,9 +52,9 @@ func (r *HistoricalRoots) MarshalSSZTo(dst []byte) ([]byte, error) {
}
// MarshalSSZ marshals HistoricalRoots into a serialized object.
func (r *HistoricalRoots) MarshalSSZ() ([]byte, error) {
marshalled := make([]byte, len(*r)*32)
for i, r32 := range *r {
func (r HistoricalRoots) MarshalSSZ() ([]byte, error) {
marshalled := make([]byte, len(r)*32)
for i, r32 := range r {
for j, rr := range r32 {
marshalled[i*32+j] = rr
}
@@ -63,17 +63,17 @@ func (r *HistoricalRoots) MarshalSSZ() ([]byte, error) {
}
// SizeSSZ returns the size of the serialized object.
func (r *HistoricalRoots) SizeSSZ() int {
return len(*r) * 32
func (r HistoricalRoots) SizeSSZ() int {
return len(r) * 32
}
// Slice converts a customtypes.HistoricalRoots object into a 2D byte slice.
func (r *HistoricalRoots) Slice() [][]byte {
func (r HistoricalRoots) Slice() [][]byte {
if r == nil {
return nil
}
hRoots := make([][]byte, len(*r))
for i, root := range *r {
hRoots := make([][]byte, len(r))
for i, root := range r {
tmp := root
hRoots[i] = tmp[:]
}

View File

@@ -7,12 +7,12 @@ import (
fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams"
)
var _ fssz.HashRoot = (RandaoMixes)([fieldparams.RandaoMixesLength][32]byte{})
var _ fssz.HashRoot = (RandaoMixes)([][32]byte{})
var _ fssz.Marshaler = (*RandaoMixes)(nil)
var _ fssz.Unmarshaler = (*RandaoMixes)(nil)
// RandaoMixes represents RANDAO mixes of the beacon state.
type RandaoMixes [fieldparams.RandaoMixesLength][32]byte
type RandaoMixes [][32]byte
// HashTreeRoot returns calculated hash root.
func (r RandaoMixes) HashTreeRoot() ([32]byte, error) {
@@ -35,7 +35,7 @@ func (r *RandaoMixes) UnmarshalSSZ(buf []byte) error {
return fmt.Errorf("expected buffer of length %d received %d", r.SizeSSZ(), len(buf))
}
var roots RandaoMixes
roots := RandaoMixes(make([][32]byte, fieldparams.RandaoMixesLength))
for i := range roots {
copy(roots[i][:], buf[i*32:(i+1)*32])
}
@@ -44,7 +44,7 @@ func (r *RandaoMixes) UnmarshalSSZ(buf []byte) error {
}
// MarshalSSZTo marshals RandaoMixes with the provided byte slice.
func (r *RandaoMixes) MarshalSSZTo(dst []byte) ([]byte, error) {
func (r RandaoMixes) MarshalSSZTo(dst []byte) ([]byte, error) {
marshalled, err := r.MarshalSSZ()
if err != nil {
return nil, err
@@ -53,7 +53,7 @@ func (r *RandaoMixes) MarshalSSZTo(dst []byte) ([]byte, error) {
}
// MarshalSSZ marshals RandaoMixes into a serialized object.
func (r *RandaoMixes) MarshalSSZ() ([]byte, error) {
func (r RandaoMixes) MarshalSSZ() ([]byte, error) {
marshalled := make([]byte, fieldparams.RandaoMixesLength*32)
for i, r32 := range r {
for j, rr := range r32 {
@@ -64,12 +64,13 @@ func (r *RandaoMixes) MarshalSSZ() ([]byte, error) {
}
// SizeSSZ returns the size of the serialized object.
func (_ *RandaoMixes) SizeSSZ() int {
func (_ RandaoMixes) SizeSSZ() int {
return fieldparams.RandaoMixesLength * 32
}
// Slice converts a customtypes.RandaoMixes object into a 2D byte slice.
func (r *RandaoMixes) Slice() [][]byte {
// Each item in the slice is a copy of the original item.
func (r RandaoMixes) Slice() [][]byte {
if r == nil {
return nil
}

View File

@@ -8,14 +8,6 @@ import (
"github.com/prysmaticlabs/prysm/v4/testing/assert"
)
func TestRandaoMixes_Casting(t *testing.T) {
var b [fieldparams.RandaoMixesLength][32]byte
d := RandaoMixes(b)
if !reflect.DeepEqual([fieldparams.RandaoMixesLength][32]byte(d), b) {
t.Errorf("Unequal: %v = %v", d, b)
}
}
func TestRandaoMixes_UnmarshalSSZ(t *testing.T) {
t.Run("Ok", func(t *testing.T) {
d := RandaoMixes{}
@@ -70,7 +62,7 @@ func TestRandaoMixes_MarshalSSZTo(t *testing.T) {
}
func TestRandaoMixes_MarshalSSZ(t *testing.T) {
d := RandaoMixes{}
d := RandaoMixes(make([][32]byte, fieldparams.RandaoMixesLength))
d[0] = [32]byte{'f', 'o', 'o'}
d[1] = [32]byte{'b', 'a', 'r'}
b, err := d.MarshalSSZ()
@@ -94,7 +86,7 @@ func TestRandaoMixes_SizeSSZ(t *testing.T) {
func TestRandaoMixes_Slice(t *testing.T) {
a, b, c := [32]byte{'a'}, [32]byte{'b'}, [32]byte{'c'}
roots := RandaoMixes{}
roots := RandaoMixes(make([][32]byte, fieldparams.RandaoMixesLength))
roots[1] = a
roots[10] = b
roots[100] = c

View File

@@ -7,12 +7,12 @@ import (
fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams"
)
var _ fssz.HashRoot = (StateRoots)([fieldparams.StateRootsLength][32]byte{})
var _ fssz.HashRoot = (StateRoots)([][32]byte{})
var _ fssz.Marshaler = (*StateRoots)(nil)
var _ fssz.Unmarshaler = (*StateRoots)(nil)
// StateRoots represents block roots of the beacon state.
type StateRoots [fieldparams.StateRootsLength][32]byte
type StateRoots [][32]byte
// HashTreeRoot returns calculated hash root.
func (r StateRoots) HashTreeRoot() ([32]byte, error) {
@@ -35,7 +35,7 @@ func (r *StateRoots) UnmarshalSSZ(buf []byte) error {
return fmt.Errorf("expected buffer of length %d received %d", r.SizeSSZ(), len(buf))
}
var roots StateRoots
roots := StateRoots(make([][32]byte, fieldparams.StateRootsLength))
for i := range roots {
copy(roots[i][:], buf[i*32:(i+1)*32])
}
@@ -44,7 +44,7 @@ func (r *StateRoots) UnmarshalSSZ(buf []byte) error {
}
// MarshalSSZTo marshals StateRoots with the provided byte slice.
func (r *StateRoots) MarshalSSZTo(dst []byte) ([]byte, error) {
func (r StateRoots) MarshalSSZTo(dst []byte) ([]byte, error) {
marshalled, err := r.MarshalSSZ()
if err != nil {
return nil, err
@@ -53,7 +53,7 @@ func (r *StateRoots) MarshalSSZTo(dst []byte) ([]byte, error) {
}
// MarshalSSZ marshals StateRoots into a serialized object.
func (r *StateRoots) MarshalSSZ() ([]byte, error) {
func (r StateRoots) MarshalSSZ() ([]byte, error) {
marshalled := make([]byte, fieldparams.StateRootsLength*32)
for i, r32 := range r {
for j, rr := range r32 {
@@ -64,12 +64,13 @@ func (r *StateRoots) MarshalSSZ() ([]byte, error) {
}
// SizeSSZ returns the size of the serialized object.
func (_ *StateRoots) SizeSSZ() int {
func (_ StateRoots) SizeSSZ() int {
return fieldparams.StateRootsLength * 32
}
// Slice converts a customtypes.StateRoots object into a 2D byte slice.
func (r *StateRoots) Slice() [][]byte {
// Each item in the slice is a copy of the original item.
func (r StateRoots) Slice() [][]byte {
if r == nil {
return nil
}

View File

@@ -8,14 +8,6 @@ import (
"github.com/prysmaticlabs/prysm/v4/testing/assert"
)
func TestStateRoots_Casting(t *testing.T) {
var b [fieldparams.StateRootsLength][32]byte
d := StateRoots(b)
if !reflect.DeepEqual([fieldparams.StateRootsLength][32]byte(d), b) {
t.Errorf("Unequal: %v = %v", d, b)
}
}
func TestStateRoots_UnmarshalSSZ(t *testing.T) {
t.Run("Ok", func(t *testing.T) {
d := StateRoots{}
@@ -70,7 +62,7 @@ func TestStateRoots_MarshalSSZTo(t *testing.T) {
}
func TestStateRoots_MarshalSSZ(t *testing.T) {
d := StateRoots{}
d := StateRoots(make([][32]byte, fieldparams.StateRootsLength))
d[0] = [32]byte{'f', 'o', 'o'}
d[1] = [32]byte{'b', 'a', 'r'}
b, err := d.MarshalSSZ()
@@ -94,7 +86,7 @@ func TestStateRoots_SizeSSZ(t *testing.T) {
func TestStateRoots_Slice(t *testing.T) {
a, b, c := [32]byte{'a'}, [32]byte{'b'}, [32]byte{'c'}
roots := StateRoots{}
roots := StateRoots(make([][32]byte, fieldparams.StateRootsLength))
roots[1] = a
roots[10] = b
roots[100] = c

View File

@@ -1,8 +1,10 @@
package state_native
import (
"fmt"
"github.com/pkg/errors"
customtypes "github.com/prysmaticlabs/prysm/v4/beacon-chain/state/state-native/custom-types"
"github.com/prysmaticlabs/prysm/v4/config/features"
consensus_types "github.com/prysmaticlabs/prysm/v4/consensus-types"
ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
)
@@ -45,26 +47,46 @@ func (b *BeaconState) latestBlockHeaderVal() *ethpb.BeaconBlockHeader {
// BlockRoots kept track of in the beacon state.
func (b *BeaconState) BlockRoots() [][]byte {
if b.blockRoots == nil {
return nil
}
b.lock.RLock()
defer b.lock.RUnlock()
return b.blockRoots.Slice()
roots := b.blockRootsVal()
if roots == nil {
return nil
}
return roots.Slice()
}
func (b *BeaconState) blockRootsVal() customtypes.BlockRoots {
if features.Get().EnableExperimentalState {
if b.blockRootsMultiValue == nil {
return nil
}
return b.blockRootsMultiValue.Value(b)
}
return b.blockRoots
}
// BlockRootAtIndex retrieves a specific block root based on an
// input index value.
func (b *BeaconState) BlockRootAtIndex(idx uint64) ([]byte, error) {
if b.blockRoots == nil {
return []byte{}, nil
}
b.lock.RLock()
defer b.lock.RUnlock()
if features.Get().EnableExperimentalState {
if b.blockRootsMultiValue == nil {
return []byte{}, nil
}
r, err := b.blockRootsMultiValue.At(b, idx)
if err != nil {
return nil, err
}
return r[:], nil
}
if b.blockRoots == nil {
return []byte{}, nil
}
r, err := b.blockRootAtIndex(idx)
if err != nil {
return nil, err
@@ -77,7 +99,7 @@ func (b *BeaconState) BlockRootAtIndex(idx uint64) ([]byte, error) {
// This assumes that a lock is already held on BeaconState.
func (b *BeaconState) blockRootAtIndex(idx uint64) ([32]byte, error) {
if uint64(len(b.blockRoots)) <= idx {
return [32]byte{}, fmt.Errorf("index %d out of range", idx)
return [32]byte{}, errors.Wrapf(consensus_types.ErrOutOfBounds, "block root index %d does not exist", idx)
}
return b.blockRoots[idx], nil
}

View File

@@ -6,6 +6,11 @@ import (
"github.com/prysmaticlabs/prysm/v4/runtime/version"
)
// Id is the identifier of the beacon state.
func (b *BeaconState) Id() uint64 {
return b.id
}
// GenesisTime of the beacon state as a uint64.
func (b *BeaconState) GenesisTime() uint64 {
b.lock.RLock()
@@ -79,16 +84,6 @@ func (b *BeaconState) HistoricalRoots() ([][]byte, error) {
return b.historicalRoots.Slice(), nil
}
// balancesLength returns the length of the balances slice.
// This assumes that a lock is already held on BeaconState.
func (b *BeaconState) balancesLength() int {
if b.balances == nil {
return 0
}
return len(b.balances)
}
// HistoricalSummaries of the beacon state.
func (b *BeaconState) HistoricalSummaries() ([]*ethpb.HistoricalSummary, error) {
if b.version < version.Capella {

View File

@@ -3,6 +3,7 @@ package state_native
import (
"github.com/prysmaticlabs/prysm/v4/beacon-chain/core/time"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state/stateutil"
"github.com/prysmaticlabs/prysm/v4/config/features"
"github.com/prysmaticlabs/prysm/v4/runtime/version"
)
@@ -56,7 +57,11 @@ func (b *BeaconState) UnrealizedCheckpointBalances() (uint64, uint64, uint64, er
return 0, 0, 0, ErrNilParticipation
}
return stateutil.UnrealizedCheckpointBalances(cp, pp, b.validators, currentEpoch)
if features.Get().EnableExperimentalState {
return stateutil.UnrealizedCheckpointBalances(cp, pp, b.validatorsVal(), currentEpoch)
} else {
return stateutil.UnrealizedCheckpointBalances(cp, pp, b.validators, currentEpoch)
}
}
// currentEpochParticipationVal corresponding to participation bits on the beacon chain.

View File

@@ -1,31 +1,54 @@
package state_native
import (
"fmt"
"github.com/pkg/errors"
customtypes "github.com/prysmaticlabs/prysm/v4/beacon-chain/state/state-native/custom-types"
"github.com/prysmaticlabs/prysm/v4/config/features"
consensus_types "github.com/prysmaticlabs/prysm/v4/consensus-types"
)
// RandaoMixes of block proposers on the beacon chain.
func (b *BeaconState) RandaoMixes() [][]byte {
if b.randaoMixes == nil {
return nil
}
b.lock.RLock()
defer b.lock.RUnlock()
return b.randaoMixes.Slice()
mixes := b.randaoMixesVal()
if mixes == nil {
return nil
}
return mixes.Slice()
}
func (b *BeaconState) randaoMixesVal() customtypes.RandaoMixes {
if features.Get().EnableExperimentalState {
if b.randaoMixesMultiValue == nil {
return nil
}
return b.randaoMixesMultiValue.Value(b)
}
return b.randaoMixes
}
// RandaoMixAtIndex retrieves a specific block root based on an
// input index value.
func (b *BeaconState) RandaoMixAtIndex(idx uint64) ([]byte, error) {
if b.randaoMixes == nil {
return nil, nil
}
b.lock.RLock()
defer b.lock.RUnlock()
if features.Get().EnableExperimentalState {
if b.randaoMixesMultiValue == nil {
return nil, nil
}
r, err := b.randaoMixesMultiValue.At(b, idx)
if err != nil {
return nil, err
}
return r[:], nil
}
if b.randaoMixes == nil {
return nil, nil
}
m, err := b.randaoMixAtIndex(idx)
if err != nil {
return nil, err
@@ -38,7 +61,7 @@ func (b *BeaconState) RandaoMixAtIndex(idx uint64) ([]byte, error) {
// This assumes that a lock is already held on BeaconState.
func (b *BeaconState) randaoMixAtIndex(idx uint64) ([32]byte, error) {
if uint64(len(b.randaoMixes)) <= idx {
return [32]byte{}, fmt.Errorf("index %d out of range", idx)
return [32]byte{}, errors.Wrapf(consensus_types.ErrOutOfBounds, "randao mix index %d does not exist", idx)
}
return b.randaoMixes[idx], nil
@@ -46,22 +69,17 @@ func (b *BeaconState) randaoMixAtIndex(idx uint64) ([32]byte, error) {
// RandaoMixesLength returns the length of the randao mixes slice.
func (b *BeaconState) RandaoMixesLength() int {
if b.randaoMixes == nil {
return 0
}
b.lock.RLock()
defer b.lock.RUnlock()
return b.randaoMixesLength()
}
// randaoMixesLength returns the length of the randao mixes slice.
// This assumes that a lock is already held on BeaconState.
func (b *BeaconState) randaoMixesLength() int {
if features.Get().EnableExperimentalState {
if b.randaoMixesMultiValue == nil {
return 0
}
return b.randaoMixesMultiValue.Len(b)
}
if b.randaoMixes == nil {
return 0
}
return len(b.randaoMixes)
}

View File

@@ -1,9 +1,10 @@
package state_native
import (
"fmt"
"github.com/pkg/errors"
customtypes "github.com/prysmaticlabs/prysm/v4/beacon-chain/state/state-native/custom-types"
"github.com/prysmaticlabs/prysm/v4/config/features"
consensus_types "github.com/prysmaticlabs/prysm/v4/consensus-types"
ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v4/runtime/version"
)
@@ -16,6 +17,18 @@ func (b *BeaconState) ToProtoUnsafe() interface{} {
}
gvrCopy := b.genesisValidatorsRoot
br := b.blockRootsVal().Slice()
sr := b.stateRootsVal().Slice()
rm := b.randaoMixesVal().Slice()
var vals []*ethpb.Validator
var bals []uint64
if features.Get().EnableExperimentalState {
vals = b.validatorsVal()
bals = b.balancesVal()
} else {
vals = b.validators
bals = b.balances
}
switch b.version {
case version.Phase0:
@@ -25,15 +38,15 @@ func (b *BeaconState) ToProtoUnsafe() interface{} {
Slot: b.slot,
Fork: b.fork,
LatestBlockHeader: b.latestBlockHeader,
BlockRoots: b.blockRoots.Slice(),
StateRoots: b.stateRoots.Slice(),
BlockRoots: br,
StateRoots: sr,
HistoricalRoots: b.historicalRoots.Slice(),
Eth1Data: b.eth1Data,
Eth1DataVotes: b.eth1DataVotes,
Eth1DepositIndex: b.eth1DepositIndex,
Validators: b.validators,
Balances: b.balances,
RandaoMixes: b.randaoMixes.Slice(),
Validators: vals,
Balances: bals,
RandaoMixes: rm,
Slashings: b.slashings,
PreviousEpochAttestations: b.previousEpochAttestations,
CurrentEpochAttestations: b.currentEpochAttestations,
@@ -49,15 +62,15 @@ func (b *BeaconState) ToProtoUnsafe() interface{} {
Slot: b.slot,
Fork: b.fork,
LatestBlockHeader: b.latestBlockHeader,
BlockRoots: b.blockRoots.Slice(),
StateRoots: b.stateRoots.Slice(),
BlockRoots: br,
StateRoots: sr,
HistoricalRoots: b.historicalRoots.Slice(),
Eth1Data: b.eth1Data,
Eth1DataVotes: b.eth1DataVotes,
Eth1DepositIndex: b.eth1DepositIndex,
Validators: b.validators,
Balances: b.balances,
RandaoMixes: b.randaoMixes.Slice(),
Validators: vals,
Balances: bals,
RandaoMixes: rm,
Slashings: b.slashings,
PreviousEpochParticipation: b.previousEpochParticipation,
CurrentEpochParticipation: b.currentEpochParticipation,
@@ -65,7 +78,7 @@ func (b *BeaconState) ToProtoUnsafe() interface{} {
PreviousJustifiedCheckpoint: b.previousJustifiedCheckpoint,
CurrentJustifiedCheckpoint: b.currentJustifiedCheckpoint,
FinalizedCheckpoint: b.finalizedCheckpoint,
InactivityScores: b.inactivityScores,
InactivityScores: b.inactivityScoresVal(),
CurrentSyncCommittee: b.currentSyncCommittee,
NextSyncCommittee: b.nextSyncCommittee,
}
@@ -76,15 +89,15 @@ func (b *BeaconState) ToProtoUnsafe() interface{} {
Slot: b.slot,
Fork: b.fork,
LatestBlockHeader: b.latestBlockHeader,
BlockRoots: b.blockRoots.Slice(),
StateRoots: b.stateRoots.Slice(),
BlockRoots: br,
StateRoots: sr,
HistoricalRoots: b.historicalRoots.Slice(),
Eth1Data: b.eth1Data,
Eth1DataVotes: b.eth1DataVotes,
Eth1DepositIndex: b.eth1DepositIndex,
Validators: b.validators,
Balances: b.balances,
RandaoMixes: b.randaoMixes.Slice(),
Validators: vals,
Balances: bals,
RandaoMixes: rm,
Slashings: b.slashings,
PreviousEpochParticipation: b.previousEpochParticipation,
CurrentEpochParticipation: b.currentEpochParticipation,
@@ -92,7 +105,7 @@ func (b *BeaconState) ToProtoUnsafe() interface{} {
PreviousJustifiedCheckpoint: b.previousJustifiedCheckpoint,
CurrentJustifiedCheckpoint: b.currentJustifiedCheckpoint,
FinalizedCheckpoint: b.finalizedCheckpoint,
InactivityScores: b.inactivityScores,
InactivityScores: b.inactivityScoresVal(),
CurrentSyncCommittee: b.currentSyncCommittee,
NextSyncCommittee: b.nextSyncCommittee,
LatestExecutionPayloadHeader: b.latestExecutionPayloadHeader,
@@ -104,15 +117,15 @@ func (b *BeaconState) ToProtoUnsafe() interface{} {
Slot: b.slot,
Fork: b.fork,
LatestBlockHeader: b.latestBlockHeader,
BlockRoots: b.blockRoots.Slice(),
StateRoots: b.stateRoots.Slice(),
BlockRoots: br,
StateRoots: sr,
HistoricalRoots: b.historicalRoots.Slice(),
Eth1Data: b.eth1Data,
Eth1DataVotes: b.eth1DataVotes,
Eth1DepositIndex: b.eth1DepositIndex,
Validators: b.validators,
Balances: b.balances,
RandaoMixes: b.randaoMixes.Slice(),
Validators: vals,
Balances: bals,
RandaoMixes: rm,
Slashings: b.slashings,
PreviousEpochParticipation: b.previousEpochParticipation,
CurrentEpochParticipation: b.currentEpochParticipation,
@@ -120,7 +133,7 @@ func (b *BeaconState) ToProtoUnsafe() interface{} {
PreviousJustifiedCheckpoint: b.previousJustifiedCheckpoint,
CurrentJustifiedCheckpoint: b.currentJustifiedCheckpoint,
FinalizedCheckpoint: b.finalizedCheckpoint,
InactivityScores: b.inactivityScores,
InactivityScores: b.inactivityScoresVal(),
CurrentSyncCommittee: b.currentSyncCommittee,
NextSyncCommittee: b.nextSyncCommittee,
LatestExecutionPayloadHeader: b.latestExecutionPayloadHeaderCapella,
@@ -135,15 +148,15 @@ func (b *BeaconState) ToProtoUnsafe() interface{} {
Slot: b.slot,
Fork: b.fork,
LatestBlockHeader: b.latestBlockHeader,
BlockRoots: b.blockRoots.Slice(),
StateRoots: b.stateRoots.Slice(),
BlockRoots: br,
StateRoots: sr,
HistoricalRoots: b.historicalRoots.Slice(),
Eth1Data: b.eth1Data,
Eth1DataVotes: b.eth1DataVotes,
Eth1DepositIndex: b.eth1DepositIndex,
Validators: b.validators,
Balances: b.balances,
RandaoMixes: b.randaoMixes.Slice(),
Validators: vals,
Balances: bals,
RandaoMixes: rm,
Slashings: b.slashings,
PreviousEpochParticipation: b.previousEpochParticipation,
CurrentEpochParticipation: b.currentEpochParticipation,
@@ -174,6 +187,14 @@ func (b *BeaconState) ToProto() interface{} {
defer b.lock.RUnlock()
gvrCopy := b.genesisValidatorsRoot
br := b.blockRootsVal().Slice()
sr := b.stateRootsVal().Slice()
rm := b.randaoMixesVal().Slice()
var inactivityScores []uint64
if b.version > version.Phase0 {
inactivityScores = b.inactivityScoresVal()
}
switch b.version {
case version.Phase0:
@@ -183,15 +204,15 @@ func (b *BeaconState) ToProto() interface{} {
Slot: b.slot,
Fork: b.forkVal(),
LatestBlockHeader: b.latestBlockHeaderVal(),
BlockRoots: b.blockRoots.Slice(),
StateRoots: b.stateRoots.Slice(),
BlockRoots: br,
StateRoots: sr,
HistoricalRoots: b.historicalRoots.Slice(),
Eth1Data: b.eth1DataVal(),
Eth1DataVotes: b.eth1DataVotesVal(),
Eth1DepositIndex: b.eth1DepositIndex,
Validators: b.validatorsVal(),
Balances: b.balancesVal(),
RandaoMixes: b.randaoMixes.Slice(),
RandaoMixes: rm,
Slashings: b.slashingsVal(),
PreviousEpochAttestations: b.previousEpochAttestationsVal(),
CurrentEpochAttestations: b.currentEpochAttestationsVal(),
@@ -207,15 +228,15 @@ func (b *BeaconState) ToProto() interface{} {
Slot: b.slot,
Fork: b.forkVal(),
LatestBlockHeader: b.latestBlockHeaderVal(),
BlockRoots: b.blockRoots.Slice(),
StateRoots: b.stateRoots.Slice(),
BlockRoots: br,
StateRoots: sr,
HistoricalRoots: b.historicalRoots.Slice(),
Eth1Data: b.eth1DataVal(),
Eth1DataVotes: b.eth1DataVotesVal(),
Eth1DepositIndex: b.eth1DepositIndex,
Validators: b.validatorsVal(),
Balances: b.balancesVal(),
RandaoMixes: b.randaoMixes.Slice(),
RandaoMixes: rm,
Slashings: b.slashingsVal(),
PreviousEpochParticipation: b.previousEpochParticipationVal(),
CurrentEpochParticipation: b.currentEpochParticipationVal(),
@@ -223,7 +244,7 @@ func (b *BeaconState) ToProto() interface{} {
PreviousJustifiedCheckpoint: b.previousJustifiedCheckpointVal(),
CurrentJustifiedCheckpoint: b.currentJustifiedCheckpointVal(),
FinalizedCheckpoint: b.finalizedCheckpointVal(),
InactivityScores: b.inactivityScoresVal(),
InactivityScores: inactivityScores,
CurrentSyncCommittee: b.currentSyncCommitteeVal(),
NextSyncCommittee: b.nextSyncCommitteeVal(),
}
@@ -234,15 +255,15 @@ func (b *BeaconState) ToProto() interface{} {
Slot: b.slot,
Fork: b.forkVal(),
LatestBlockHeader: b.latestBlockHeaderVal(),
BlockRoots: b.blockRoots.Slice(),
StateRoots: b.stateRoots.Slice(),
BlockRoots: br,
StateRoots: sr,
HistoricalRoots: b.historicalRoots.Slice(),
Eth1Data: b.eth1DataVal(),
Eth1DataVotes: b.eth1DataVotesVal(),
Eth1DepositIndex: b.eth1DepositIndex,
Validators: b.validatorsVal(),
Balances: b.balancesVal(),
RandaoMixes: b.randaoMixes.Slice(),
RandaoMixes: rm,
Slashings: b.slashingsVal(),
PreviousEpochParticipation: b.previousEpochParticipationVal(),
CurrentEpochParticipation: b.currentEpochParticipationVal(),
@@ -250,7 +271,7 @@ func (b *BeaconState) ToProto() interface{} {
PreviousJustifiedCheckpoint: b.previousJustifiedCheckpointVal(),
CurrentJustifiedCheckpoint: b.currentJustifiedCheckpointVal(),
FinalizedCheckpoint: b.finalizedCheckpointVal(),
InactivityScores: b.inactivityScoresVal(),
InactivityScores: inactivityScores,
CurrentSyncCommittee: b.currentSyncCommitteeVal(),
NextSyncCommittee: b.nextSyncCommitteeVal(),
LatestExecutionPayloadHeader: b.latestExecutionPayloadHeaderVal(),
@@ -262,15 +283,15 @@ func (b *BeaconState) ToProto() interface{} {
Slot: b.slot,
Fork: b.forkVal(),
LatestBlockHeader: b.latestBlockHeaderVal(),
BlockRoots: b.blockRoots.Slice(),
StateRoots: b.stateRoots.Slice(),
BlockRoots: br,
StateRoots: sr,
HistoricalRoots: b.historicalRoots.Slice(),
Eth1Data: b.eth1DataVal(),
Eth1DataVotes: b.eth1DataVotesVal(),
Eth1DepositIndex: b.eth1DepositIndex,
Validators: b.validatorsVal(),
Balances: b.balancesVal(),
RandaoMixes: b.randaoMixes.Slice(),
RandaoMixes: rm,
Slashings: b.slashingsVal(),
PreviousEpochParticipation: b.previousEpochParticipationVal(),
CurrentEpochParticipation: b.currentEpochParticipationVal(),
@@ -278,7 +299,7 @@ func (b *BeaconState) ToProto() interface{} {
PreviousJustifiedCheckpoint: b.previousJustifiedCheckpointVal(),
CurrentJustifiedCheckpoint: b.currentJustifiedCheckpointVal(),
FinalizedCheckpoint: b.finalizedCheckpointVal(),
InactivityScores: b.inactivityScoresVal(),
InactivityScores: inactivityScores,
CurrentSyncCommittee: b.currentSyncCommitteeVal(),
NextSyncCommittee: b.nextSyncCommitteeVal(),
LatestExecutionPayloadHeader: b.latestExecutionPayloadHeaderCapellaVal(),
@@ -293,15 +314,15 @@ func (b *BeaconState) ToProto() interface{} {
Slot: b.slot,
Fork: b.forkVal(),
LatestBlockHeader: b.latestBlockHeaderVal(),
BlockRoots: b.blockRoots.Slice(),
StateRoots: b.stateRoots.Slice(),
BlockRoots: br,
StateRoots: sr,
HistoricalRoots: b.historicalRoots.Slice(),
Eth1Data: b.eth1DataVal(),
Eth1DataVotes: b.eth1DataVotesVal(),
Eth1DepositIndex: b.eth1DepositIndex,
Validators: b.validatorsVal(),
Balances: b.balancesVal(),
RandaoMixes: b.randaoMixes.Slice(),
RandaoMixes: rm,
Slashings: b.slashingsVal(),
PreviousEpochParticipation: b.previousEpochParticipationVal(),
CurrentEpochParticipation: b.currentEpochParticipationVal(),
@@ -324,26 +345,46 @@ func (b *BeaconState) ToProto() interface{} {
// StateRoots kept track of in the beacon state.
func (b *BeaconState) StateRoots() [][]byte {
if b.stateRoots == nil {
return nil
}
b.lock.RLock()
defer b.lock.RUnlock()
return b.stateRoots.Slice()
roots := b.stateRootsVal()
if roots == nil {
return nil
}
return roots.Slice()
}
func (b *BeaconState) stateRootsVal() customtypes.StateRoots {
if features.Get().EnableExperimentalState {
if b.stateRootsMultiValue == nil {
return nil
}
return b.stateRootsMultiValue.Value(b)
}
return b.stateRoots
}
// StateRootAtIndex retrieves a specific state root based on an
// input index value.
func (b *BeaconState) StateRootAtIndex(idx uint64) ([]byte, error) {
if b.stateRoots == nil {
return nil, nil
}
b.lock.RLock()
defer b.lock.RUnlock()
if features.Get().EnableExperimentalState {
if b.stateRootsMultiValue == nil {
return nil, nil
}
r, err := b.stateRootsMultiValue.At(b, idx)
if err != nil {
return nil, err
}
return r[:], nil
}
if b.stateRoots == nil {
return nil, nil
}
r, err := b.stateRootAtIndex(idx)
if err != nil {
return nil, err
@@ -354,9 +395,11 @@ func (b *BeaconState) StateRootAtIndex(idx uint64) ([]byte, error) {
// stateRootAtIndex retrieves a specific state root based on an
// input index value.
// This assumes that a lock is already held on BeaconState.
//
// WARNING: This function does not work with the multi-value slice feature.
func (b *BeaconState) stateRootAtIndex(idx uint64) ([32]byte, error) {
if uint64(len(b.stateRoots)) <= idx {
return [32]byte{}, fmt.Errorf("index %d out of range", idx)
return [32]byte{}, errors.Wrapf(consensus_types.ErrOutOfBounds, "state root index %d does not exist", idx)
}
return b.stateRoots[idx], nil
}

View File

@@ -1,57 +1,42 @@
package state_native
import (
"fmt"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state"
"github.com/prysmaticlabs/prysm/v4/config/features"
fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams"
consensus_types "github.com/prysmaticlabs/prysm/v4/consensus-types"
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v4/runtime/version"
)
// ValidatorIndexOutOfRangeError represents an error scenario where a validator does not exist
// at a given index in the validator's array.
type ValidatorIndexOutOfRangeError struct {
message string
}
// NewValidatorIndexOutOfRangeError creates a new error instance.
func NewValidatorIndexOutOfRangeError(index primitives.ValidatorIndex) ValidatorIndexOutOfRangeError {
return ValidatorIndexOutOfRangeError{
message: fmt.Sprintf("index %d out of range", index),
}
}
// Error returns the underlying error message.
func (e *ValidatorIndexOutOfRangeError) Error() string {
return e.message
}
// Validators participating in consensus on the beacon chain.
func (b *BeaconState) Validators() []*ethpb.Validator {
if b.validators == nil {
return nil
}
b.lock.RLock()
defer b.lock.RUnlock()
return b.validatorsVal()
}
// validatorsVal participating in consensus on the beacon chain.
// This assumes that a lock is already held on BeaconState.
func (b *BeaconState) validatorsVal() []*ethpb.Validator {
if b.validators == nil {
return nil
var v []*ethpb.Validator
if features.Get().EnableExperimentalState {
if b.validatorsMultiValue == nil {
return nil
}
v = b.validatorsMultiValue.Value(b)
} else {
if b.validators == nil {
return nil
}
v = b.validators
}
res := make([]*ethpb.Validator, len(b.validators))
res := make([]*ethpb.Validator, len(v))
for i := 0; i < len(res); i++ {
val := b.validators[i]
val := v[i]
if val == nil {
continue
}
@@ -80,19 +65,42 @@ func (b *BeaconState) validatorsReferences() []*ethpb.Validator {
return res
}
func (b *BeaconState) validatorsLen() int {
if features.Get().EnableExperimentalState {
if b.validatorsMultiValue == nil {
return 0
}
return b.validatorsMultiValue.Len(b)
}
return len(b.validators)
}
// ValidatorAtIndex is the validator at the provided index.
func (b *BeaconState) ValidatorAtIndex(idx primitives.ValidatorIndex) (*ethpb.Validator, error) {
b.lock.RLock()
defer b.lock.RUnlock()
return b.validatorAtIndex(idx)
}
func (b *BeaconState) validatorAtIndex(idx primitives.ValidatorIndex) (*ethpb.Validator, error) {
if features.Get().EnableExperimentalState {
if b.validatorsMultiValue == nil {
return &ethpb.Validator{}, nil
}
v, err := b.validatorsMultiValue.At(b, uint64(idx))
if err != nil {
return nil, err
}
return ethpb.CopyValidator(v), nil
}
if b.validators == nil {
return &ethpb.Validator{}, nil
}
if uint64(len(b.validators)) <= uint64(idx) {
e := NewValidatorIndexOutOfRangeError(idx)
return nil, &e
return nil, errors.Wrapf(consensus_types.ErrOutOfBounds, "validator index %d does not exist", idx)
}
b.lock.RLock()
defer b.lock.RUnlock()
val := b.validators[idx]
return ethpb.CopyValidator(val), nil
}
@@ -100,18 +108,28 @@ func (b *BeaconState) ValidatorAtIndex(idx primitives.ValidatorIndex) (*ethpb.Va
// ValidatorAtIndexReadOnly is the validator at the provided index. This method
// doesn't clone the validator.
func (b *BeaconState) ValidatorAtIndexReadOnly(idx primitives.ValidatorIndex) (state.ReadOnlyValidator, error) {
b.lock.RLock()
defer b.lock.RUnlock()
if features.Get().EnableExperimentalState {
if b.validatorsMultiValue == nil {
return nil, state.ErrNilValidatorsInState
}
v, err := b.validatorsMultiValue.At(b, uint64(idx))
if err != nil {
return nil, err
}
return NewValidator(v)
}
if b.validators == nil {
return nil, state.ErrNilValidatorsInState
}
if uint64(len(b.validators)) <= uint64(idx) {
e := NewValidatorIndexOutOfRangeError(idx)
return nil, &e
return nil, errors.Wrapf(consensus_types.ErrOutOfBounds, "validator index %d does not exist", idx)
}
b.lock.RLock()
defer b.lock.RUnlock()
return NewValidator(b.validators[idx])
val := b.validators[idx]
return NewValidator(val)
}
// ValidatorIndexByPubkey returns a given validator by its 48-byte public key.
@@ -121,7 +139,13 @@ func (b *BeaconState) ValidatorIndexByPubkey(key [fieldparams.BLSPubkeyLength]by
}
b.lock.RLock()
defer b.lock.RUnlock()
numOfVals := len(b.validators)
var numOfVals int
if features.Get().EnableExperimentalState {
numOfVals = b.validatorsMultiValue.Len(b)
} else {
numOfVals = len(b.validators)
}
idx, ok := b.valMapHandler.Get(key)
if ok && primitives.ValidatorIndex(numOfVals) <= idx {
@@ -133,16 +157,27 @@ func (b *BeaconState) ValidatorIndexByPubkey(key [fieldparams.BLSPubkeyLength]by
// PubkeyAtIndex returns the pubkey at the given
// validator index.
func (b *BeaconState) PubkeyAtIndex(idx primitives.ValidatorIndex) [fieldparams.BLSPubkeyLength]byte {
if uint64(idx) >= uint64(len(b.validators)) {
return [fieldparams.BLSPubkeyLength]byte{}
}
b.lock.RLock()
defer b.lock.RUnlock()
if b.validators[idx] == nil {
var v *ethpb.Validator
if features.Get().EnableExperimentalState {
var err error
v, err = b.validatorsMultiValue.At(b, uint64(idx))
if err != nil {
return [fieldparams.BLSPubkeyLength]byte{}
}
} else {
if uint64(idx) >= uint64(len(b.validators)) {
return [fieldparams.BLSPubkeyLength]byte{}
}
v = b.validators[idx]
}
if v == nil {
return [fieldparams.BLSPubkeyLength]byte{}
}
return bytesutil.ToBytes48(b.validators[idx].PublicKey)
return bytesutil.ToBytes48(v.PublicKey)
}
// NumValidators returns the size of the validator registry.
@@ -150,26 +185,54 @@ func (b *BeaconState) NumValidators() int {
b.lock.RLock()
defer b.lock.RUnlock()
return len(b.validators)
return b.validatorsLen()
}
// ReadFromEveryValidator reads values from every validator and applies it to the provided function.
//
// WARNING: This method is potentially unsafe, as it exposes the actual validator registry.
func (b *BeaconState) ReadFromEveryValidator(f func(idx int, val state.ReadOnlyValidator) error) error {
if b.validators == nil {
return errors.New("nil validators in state")
}
b.lock.RLock()
defer b.lock.RUnlock()
if features.Get().EnableExperimentalState {
return b.readFromEveryValidatorMVSlice(f)
}
if b.validators == nil {
return state.ErrNilValidatorsInState
}
validators := b.validators
b.lock.RUnlock()
for i, v := range validators {
v, err := NewValidator(v)
if err != nil {
return err
}
if err := f(i, v); err != nil {
if err = f(i, v); err != nil {
return err
}
}
return nil
}
// WARNING: This function works only for the multi-value slice feature.
func (b *BeaconState) readFromEveryValidatorMVSlice(f func(idx int, val state.ReadOnlyValidator) error) error {
if b.validatorsMultiValue == nil {
return state.ErrNilValidatorsInState
}
l := b.validatorsMultiValue.Len(b)
for i := 0; i < l; i++ {
v, err := b.validatorsMultiValue.At(b, uint64(i))
if err != nil {
return err
}
rov, err := NewValidator(v)
if err != nil {
return err
}
if err = f(i, rov); err != nil {
return err
}
}
@@ -178,23 +241,22 @@ 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.balances == nil {
return nil
}
b.lock.RLock()
defer b.lock.RUnlock()
return b.balancesVal()
}
// balancesVal of validators participating in consensus on the beacon chain.
// This assumes that a lock is already held on BeaconState.
func (b *BeaconState) balancesVal() []uint64 {
if features.Get().EnableExperimentalState {
if b.balancesMultiValue == nil {
return nil
}
return b.balancesMultiValue.Value(b)
}
if b.balances == nil {
return nil
}
res := make([]uint64, len(b.balances))
copy(res, b.balances)
return res
@@ -202,29 +264,40 @@ func (b *BeaconState) balancesVal() []uint64 {
// BalanceAtIndex of validator with the provided index.
func (b *BeaconState) BalanceAtIndex(idx primitives.ValidatorIndex) (uint64, error) {
if b.balances == nil {
return 0, nil
}
b.lock.RLock()
defer b.lock.RUnlock()
return b.balanceAtIndex(idx)
}
func (b *BeaconState) balanceAtIndex(idx primitives.ValidatorIndex) (uint64, error) {
if features.Get().EnableExperimentalState {
if b.balancesMultiValue == nil {
return 0, nil
}
return b.balancesMultiValue.At(b, uint64(idx))
}
if b.balances == nil {
return 0, nil
}
if uint64(len(b.balances)) <= uint64(idx) {
return 0, fmt.Errorf("index of %d does not exist", idx)
return 0, errors.Wrapf(consensus_types.ErrOutOfBounds, "balance index %d does not exist", idx)
}
return b.balances[idx], nil
}
// BalancesLength returns the length of the balances slice.
func (b *BeaconState) BalancesLength() int {
if b.balances == nil {
return 0
}
b.lock.RLock()
defer b.lock.RUnlock()
return b.balancesLength()
if features.Get().EnableExperimentalState {
if b.balancesMultiValue == nil {
return 0
}
return b.balancesMultiValue.Len(b)
}
return len(b.balances)
}
// Slashings of validators on the beacon chain.
@@ -257,23 +330,22 @@ func (b *BeaconState) InactivityScores() ([]uint64, error) {
return nil, errNotSupported("InactivityScores", b.version)
}
if b.inactivityScores == nil {
return nil, nil
}
b.lock.RLock()
defer b.lock.RUnlock()
return b.inactivityScoresVal(), nil
}
// inactivityScoresVal of validators participating in consensus on the beacon chain.
// This assumes that a lock is already held on BeaconState.
func (b *BeaconState) inactivityScoresVal() []uint64 {
if features.Get().EnableExperimentalState {
if b.inactivityScoresMultiValue == nil {
return nil
}
return b.inactivityScoresMultiValue.Value(b)
}
if b.inactivityScores == nil {
return nil
}
res := make([]uint64, len(b.inactivityScores))
copy(res, b.inactivityScores)
return res

View File

@@ -52,11 +52,6 @@ func TestBeaconState_ValidatorAtIndexReadOnly_HandlesNilSlice_Deneb(t *testing.T
})
}
func TestValidatorIndexOutOfRangeError(t *testing.T) {
err := statenative.NewValidatorIndexOutOfRangeError(1)
require.Equal(t, err.Error(), "index 1 out of range")
}
func TestValidatorIndexes(t *testing.T) {
dState, _ := util.DeterministicGenesisState(t, 10)
byteValue := dState.PubkeyAtIndex(1)

View File

@@ -1,6 +1,7 @@
package state_native
import (
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/v4/config/params"
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
@@ -54,10 +55,17 @@ func (b *BeaconState) ExpectedWithdrawals() ([]*enginev1.Withdrawal, error) {
withdrawalIndex := b.nextWithdrawalIndex
epoch := slots.ToEpoch(b.slot)
bound := mathutil.Min(uint64(len(b.validators)), params.BeaconConfig().MaxValidatorsPerWithdrawalsSweep)
validatorsLen := b.validatorsLen()
bound := mathutil.Min(uint64(validatorsLen), params.BeaconConfig().MaxValidatorsPerWithdrawalsSweep)
for i := uint64(0); i < bound; i++ {
val := b.validators[validatorIndex]
balance := b.balances[validatorIndex]
val, err := b.validatorAtIndex(validatorIndex)
if err != nil {
return nil, errors.Wrapf(err, "could not retrieve validator at index %d", validatorIndex)
}
balance, err := b.balanceAtIndex(validatorIndex)
if err != nil {
return nil, errors.Wrapf(err, "could not retrieve balance at index %d", validatorIndex)
}
if balance > 0 && isFullyWithdrawableValidator(val, epoch) {
withdrawals = append(withdrawals, &enginev1.Withdrawal{
Index: withdrawalIndex,
@@ -79,7 +87,7 @@ func (b *BeaconState) ExpectedWithdrawals() ([]*enginev1.Withdrawal, error) {
break
}
validatorIndex += 1
if uint64(validatorIndex) == uint64(len(b.validators)) {
if uint64(validatorIndex) == uint64(validatorsLen) {
validatorIndex = 0
}
}

View File

@@ -65,22 +65,14 @@ func ComputeFieldRootsWithHasher(ctx context.Context, state *BeaconState) ([][]b
fieldRoots[types.LatestBlockHeader.RealPosition()] = headerHashTreeRoot[:]
// BlockRoots array root.
bRoots := make([][]byte, len(state.blockRoots))
for i := range bRoots {
bRoots[i] = state.blockRoots[i][:]
}
blockRootsRoot, err := stateutil.ArraysRoot(bRoots, fieldparams.BlockRootsLength)
blockRootsRoot, err := stateutil.ArraysRoot(state.blockRootsVal().Slice(), fieldparams.BlockRootsLength)
if err != nil {
return nil, errors.Wrap(err, "could not compute block roots merkleization")
}
fieldRoots[types.BlockRoots.RealPosition()] = blockRootsRoot[:]
// StateRoots array root.
sRoots := make([][]byte, len(state.stateRoots))
for i := range sRoots {
sRoots[i] = state.stateRoots[i][:]
}
stateRootsRoot, err := stateutil.ArraysRoot(sRoots, fieldparams.StateRootsLength)
stateRootsRoot, err := stateutil.ArraysRoot(state.stateRootsVal().Slice(), fieldparams.StateRootsLength)
if err != nil {
return nil, errors.Wrap(err, "could not compute state roots merkleization")
}
@@ -118,25 +110,21 @@ func ComputeFieldRootsWithHasher(ctx context.Context, state *BeaconState) ([][]b
fieldRoots[types.Eth1DepositIndex.RealPosition()] = eth1DepositBuf[:]
// Validators slice root.
validatorsRoot, err := stateutil.ValidatorRegistryRoot(state.validators)
validatorsRoot, err := stateutil.ValidatorRegistryRoot(state.validatorsVal())
if err != nil {
return nil, errors.Wrap(err, "could not compute validator registry merkleization")
}
fieldRoots[types.Validators.RealPosition()] = validatorsRoot[:]
// Balances slice root.
balancesRoot, err := stateutil.Uint64ListRootWithRegistryLimit(state.balances)
balancesRoot, err := stateutil.Uint64ListRootWithRegistryLimit(state.balancesVal())
if err != nil {
return nil, errors.Wrap(err, "could not compute validator balances merkleization")
}
fieldRoots[types.Balances.RealPosition()] = balancesRoot[:]
// RandaoMixes array root.
mixes := make([][]byte, len(state.randaoMixes))
for i := range mixes {
mixes[i] = state.randaoMixes[i][:]
}
randaoRootsRoot, err := stateutil.ArraysRoot(mixes, fieldparams.RandaoMixesLength)
randaoRootsRoot, err := stateutil.ArraysRoot(state.randaoMixesVal().Slice(), fieldparams.RandaoMixesLength)
if err != nil {
return nil, errors.Wrap(err, "could not compute randao roots merkleization")
}
@@ -208,7 +196,7 @@ func ComputeFieldRootsWithHasher(ctx context.Context, state *BeaconState) ([][]b
if state.version >= version.Altair {
// Inactivity scores root.
inactivityScoresRoot, err := stateutil.Uint64ListRootWithRegistryLimit(state.inactivityScores)
inactivityScoresRoot, err := stateutil.Uint64ListRootWithRegistryLimit(state.inactivityScoresVal())
if err != nil {
return nil, errors.Wrap(err, "could not compute inactivityScoreRoot")
}

View File

@@ -0,0 +1,145 @@
package state_native
import (
"runtime"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams"
multi_value_slice "github.com/prysmaticlabs/prysm/v4/container/multi-value-slice"
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
)
var (
multiValueRandaoMixesCountGauge = promauto.NewGauge(prometheus.GaugeOpts{
Name: "multi_value_randao_mixes_count",
})
multiValueBlockRootsCountGauge = promauto.NewGauge(prometheus.GaugeOpts{
Name: "multi_value_block_roots_count",
})
multiValueStateRootsCountGauge = promauto.NewGauge(prometheus.GaugeOpts{
Name: "multi_value_state_roots_count",
})
multiValueBalancesCountGauge = promauto.NewGauge(prometheus.GaugeOpts{
Name: "multi_value_balances_count",
})
multiValueValidatorsCountGauge = promauto.NewGauge(prometheus.GaugeOpts{
Name: "multi_value_validators_count",
})
multiValueInactivityScoresCountGauge = promauto.NewGauge(prometheus.GaugeOpts{
Name: "multi_value_inactivity_scores_count",
})
)
// MultiValueRandaoMixes is a multi-value slice of randao mixes.
type MultiValueRandaoMixes = multi_value_slice.Slice[[32]byte, *BeaconState]
// NewMultiValueRandaoMixes creates a new slice whose shared items will be populated with copies of input values.
func NewMultiValueRandaoMixes(mixes [][]byte) *MultiValueRandaoMixes {
items := make([][32]byte, fieldparams.RandaoMixesLength)
for i, v := range mixes {
items[i] = [32]byte(bytesutil.PadTo(v, 32))
}
mv := &MultiValueRandaoMixes{}
mv.Init(items)
multiValueRandaoMixesCountGauge.Inc()
runtime.SetFinalizer(mv, randaoMixesFinalizer)
return mv
}
// MultiValueBlockRoots is a multi-value slice of block roots.
type MultiValueBlockRoots = multi_value_slice.Slice[[32]byte, *BeaconState]
// NewMultiValueBlockRoots creates a new slice whose shared items will be populated with copies of input values.
func NewMultiValueBlockRoots(roots [][]byte) *MultiValueBlockRoots {
items := make([][32]byte, fieldparams.BlockRootsLength)
for i, v := range roots {
items[i] = [32]byte(bytesutil.PadTo(v, 32))
}
mv := &MultiValueBlockRoots{}
mv.Init(items)
multiValueBlockRootsCountGauge.Inc()
runtime.SetFinalizer(mv, blockRootsFinalizer)
return mv
}
// MultiValueStateRoots is a multi-value slice of state roots.
type MultiValueStateRoots = multi_value_slice.Slice[[32]byte, *BeaconState]
// NewMultiValueStateRoots creates a new slice whose shared items will be populated with copies of input values.
func NewMultiValueStateRoots(roots [][]byte) *MultiValueStateRoots {
items := make([][32]byte, fieldparams.StateRootsLength)
for i, v := range roots {
items[i] = [32]byte(bytesutil.PadTo(v, 32))
}
mv := &MultiValueStateRoots{}
mv.Init(items)
multiValueStateRootsCountGauge.Inc()
runtime.SetFinalizer(mv, stateRootsFinalizer)
return mv
}
// MultiValueBalances is a multi-value slice of balances.
type MultiValueBalances = multi_value_slice.Slice[uint64, *BeaconState]
// NewMultiValueBalances creates a new slice whose shared items will be populated with copies of input values.
func NewMultiValueBalances(balances []uint64) *MultiValueBalances {
items := make([]uint64, len(balances))
copy(items, balances)
mv := &MultiValueBalances{}
mv.Init(items)
multiValueBalancesCountGauge.Inc()
runtime.SetFinalizer(mv, balancesFinalizer)
return mv
}
// MultiValueInactivityScores is a multi-value slice of inactivity scores.
type MultiValueInactivityScores = multi_value_slice.Slice[uint64, *BeaconState]
// NewMultiValueInactivityScores creates a new slice whose shared items will be populated with copies of input values.
func NewMultiValueInactivityScores(scores []uint64) *MultiValueInactivityScores {
items := make([]uint64, len(scores))
copy(items, scores)
mv := &MultiValueInactivityScores{}
mv.Init(items)
multiValueInactivityScoresCountGauge.Inc()
runtime.SetFinalizer(mv, inactivityScoresFinalizer)
return mv
}
// MultiValueValidators is a multi-value slice of validator references.
type MultiValueValidators = multi_value_slice.Slice[*ethpb.Validator, *BeaconState]
// NewMultiValueValidators creates a new slice whose shared items will be populated with input values.
func NewMultiValueValidators(vals []*ethpb.Validator) *MultiValueValidators {
mv := &MultiValueValidators{}
mv.Init(vals)
multiValueValidatorsCountGauge.Inc()
runtime.SetFinalizer(mv, validatorsFinalizer)
return mv
}
func randaoMixesFinalizer(m *MultiValueRandaoMixes) {
multiValueRandaoMixesCountGauge.Dec()
}
func blockRootsFinalizer(m *MultiValueBlockRoots) {
multiValueBlockRootsCountGauge.Dec()
}
func stateRootsFinalizer(m *MultiValueStateRoots) {
multiValueStateRootsCountGauge.Dec()
}
func balancesFinalizer(m *MultiValueBalances) {
multiValueBalancesCountGauge.Dec()
}
func validatorsFinalizer(m *MultiValueValidators) {
multiValueValidatorsCountGauge.Dec()
}
func inactivityScoresFinalizer(m *MultiValueInactivityScores) {
multiValueInactivityScoresCountGauge.Dec()
}

View File

@@ -0,0 +1,71 @@
package state_native
import (
"testing"
"github.com/prysmaticlabs/prysm/v4/config/features"
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v4/testing/require"
)
func FuzzMultiValueBalances(f *testing.F) {
resetFn := features.InitWithReset(&features.Flags{
EnableExperimentalState: true,
})
defer resetFn()
bals := make([]uint64, 65536)
firstState, err := InitializeFromProtoPhase0(&ethpb.BeaconState{Balances: bals})
require.NoError(f, err)
f.Fuzz(func(t *testing.T, index uint16, value uint64) {
secondState := firstState
// there's a 25% chance we will copy the state
copyState := index%4 == 0
if copyState {
secondState = firstState.Copy()
}
if index%2 == 0 {
// update existing balance
oldValue, err := firstState.BalanceAtIndex(primitives.ValidatorIndex(index))
require.NoError(t, err)
require.NoError(t, secondState.UpdateBalancesAtIndex(primitives.ValidatorIndex(index), value))
firstValue, err := firstState.BalanceAtIndex(primitives.ValidatorIndex(index))
require.NoError(t, err)
secondValue, err := secondState.BalanceAtIndex(primitives.ValidatorIndex(index))
require.NoError(t, err)
if copyState {
require.Equal(t, oldValue, firstValue)
require.Equal(t, value, secondValue)
} else {
require.Equal(t, value, firstValue)
require.Equal(t, value, secondValue)
}
} else {
// append new balance
firstLength := firstState.BalancesLength()
require.NoError(t, secondState.AppendBalance(value))
if copyState {
require.Equal(t, firstLength, secondState.BalancesLength())
v, err := firstState.BalanceAtIndex(primitives.ValidatorIndex(firstLength - 1))
require.NoError(t, err)
require.Equal(t, value, v)
v, err = secondState.BalanceAtIndex(primitives.ValidatorIndex(secondState.BalancesLength() - 1))
require.NoError(t, err)
require.Equal(t, value, v)
} else {
require.Equal(t, firstLength+1, secondState.BalancesLength())
v, err := secondState.BalanceAtIndex(primitives.ValidatorIndex(secondState.BalancesLength() - 1))
require.NoError(t, err)
require.Equal(t, value, v)
}
}
})
}

View File

@@ -38,7 +38,7 @@ func TestStateReferenceSharing_Finalizer_Phase0(t *testing.T) {
b, ok := copied.(*BeaconState)
require.Equal(t, true, ok)
assert.Equal(t, uint(2), b.sharedFieldReferences[types.RandaoMixes].Refs(), "Expected 2 shared references to RANDAO mixes")
require.NoError(t, b.UpdateRandaoMixesAtIndex(0, []byte("bar")))
require.NoError(t, b.UpdateRandaoMixesAtIndex(0, bytesutil.ToBytes32([]byte("bar"))))
if b.sharedFieldReferences[types.RandaoMixes].Refs() != 1 || a.sharedFieldReferences[types.RandaoMixes].Refs() != 1 {
t.Error("Expected 1 shared reference to RANDAO mix for both a and b")
}
@@ -67,7 +67,7 @@ func TestStateReferenceSharing_Finalizer_Altair(t *testing.T) {
b, ok := copied.(*BeaconState)
require.Equal(t, true, ok)
assert.Equal(t, uint(2), b.sharedFieldReferences[types.RandaoMixes].Refs(), "Expected 2 shared references to RANDAO mixes")
require.NoError(t, b.UpdateRandaoMixesAtIndex(0, []byte("bar")))
require.NoError(t, b.UpdateRandaoMixesAtIndex(0, bytesutil.ToBytes32([]byte("bar"))))
if b.sharedFieldReferences[types.RandaoMixes].Refs() != 1 || a.sharedFieldReferences[types.RandaoMixes].Refs() != 1 {
t.Error("Expected 1 shared reference to RANDAO mix for both a and b")
}
@@ -96,7 +96,7 @@ func TestStateReferenceSharing_Finalizer_Bellatrix(t *testing.T) {
b, ok := copied.(*BeaconState)
require.Equal(t, true, ok)
assert.Equal(t, uint(2), b.sharedFieldReferences[types.RandaoMixes].Refs(), "Expected 2 shared references to RANDAO mixes")
require.NoError(t, b.UpdateRandaoMixesAtIndex(0, []byte("bar")))
require.NoError(t, b.UpdateRandaoMixesAtIndex(0, bytesutil.ToBytes32([]byte("bar"))))
if b.sharedFieldReferences[types.RandaoMixes].Refs() != 1 || a.sharedFieldReferences[types.RandaoMixes].Refs() != 1 {
t.Error("Expected 1 shared reference to RANDAO mix for both a and b")
}
@@ -125,7 +125,7 @@ func TestStateReferenceSharing_Finalizer_Capella(t *testing.T) {
b, ok := copied.(*BeaconState)
require.Equal(t, true, ok)
assert.Equal(t, uint(2), b.sharedFieldReferences[types.RandaoMixes].Refs(), "Expected 2 shared references to RANDAO mixes")
require.NoError(t, b.UpdateRandaoMixesAtIndex(0, []byte("bar")))
require.NoError(t, b.UpdateRandaoMixesAtIndex(0, bytesutil.ToBytes32([]byte("bar"))))
if b.sharedFieldReferences[types.RandaoMixes].Refs() != 1 || a.sharedFieldReferences[types.RandaoMixes].Refs() != 1 {
t.Error("Expected 1 shared reference to RANDAO mix for both a and b")
}
@@ -154,7 +154,7 @@ func TestStateReferenceSharing_Finalizer_Deneb(t *testing.T) {
b, ok := copied.(*BeaconState)
require.Equal(t, true, ok)
assert.Equal(t, uint(2), b.sharedFieldReferences[types.RandaoMixes].Refs(), "Expected 2 shared references to RANDAO mixes")
require.NoError(t, b.UpdateRandaoMixesAtIndex(0, []byte("bar")))
require.NoError(t, b.UpdateRandaoMixesAtIndex(0, bytesutil.ToBytes32([]byte("bar"))))
if b.sharedFieldReferences[types.RandaoMixes].Refs() != 1 || a.sharedFieldReferences[types.RandaoMixes].Refs() != 1 {
t.Error("Expected 1 shared reference to RANDAO mix for both a and b")
}
@@ -482,7 +482,7 @@ func TestStateReferenceCopy_NoUnexpectedRandaoMutation_Phase0(t *testing.T) {
assertValFound(t, mixesB, val1[:])
// Mutator should only affect calling state: a.
require.NoError(t, a.UpdateRandaoMixesAtIndex(0, val2[:]))
require.NoError(t, a.UpdateRandaoMixesAtIndex(0, val2))
// Assert no shared state mutation occurred only on state a (copy on write).
assertValFound(t, a.RandaoMixes(), val2[:])
@@ -526,7 +526,7 @@ func TestStateReferenceCopy_NoUnexpectedRandaoMutation_Altair(t *testing.T) {
assertValFound(t, mixesB, val1[:])
// Mutator should only affect calling state: a.
require.NoError(t, a.UpdateRandaoMixesAtIndex(0, val2[:]))
require.NoError(t, a.UpdateRandaoMixesAtIndex(0, val2))
// Assert no shared state mutation occurred only on state a (copy on write).
assertValFound(t, a.RandaoMixes(), val2[:])
@@ -570,7 +570,7 @@ func TestStateReferenceCopy_NoUnexpectedRandaoMutation_Bellatrix(t *testing.T) {
assertValFound(t, mixesB, val1[:])
// Mutator should only affect calling state: a.
require.NoError(t, a.UpdateRandaoMixesAtIndex(0, val2[:]))
require.NoError(t, a.UpdateRandaoMixesAtIndex(0, val2))
// Assert no shared state mutation occurred only on state a (copy on write).
assertValFound(t, a.RandaoMixes(), val2[:])
@@ -614,7 +614,7 @@ func TestStateReferenceCopy_NoUnexpectedRandaoMutation_Capella(t *testing.T) {
assertValFound(t, mixesB, val1[:])
// Mutator should only affect calling state: a.
require.NoError(t, a.UpdateRandaoMixesAtIndex(0, val2[:]))
require.NoError(t, a.UpdateRandaoMixesAtIndex(0, val2))
// Assert no shared state mutation occurred only on state a (copy on write).
assertValFound(t, a.RandaoMixes(), val2[:])
@@ -658,7 +658,7 @@ func TestStateReferenceCopy_NoUnexpectedRandaoMutation_Deneb(t *testing.T) {
assertValFound(t, mixesB, val1[:])
// Mutator should only affect calling state: a.
require.NoError(t, a.UpdateRandaoMixesAtIndex(0, val2[:]))
require.NoError(t, a.UpdateRandaoMixesAtIndex(0, val2))
// Assert no shared state mutation occurred only on state a (copy on write).
assertValFound(t, a.RandaoMixes(), val2[:])

View File

@@ -1,12 +1,12 @@
package state_native
import (
"fmt"
customtypes "github.com/prysmaticlabs/prysm/v4/beacon-chain/state/state-native/custom-types"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state/state-native/types"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state/stateutil"
"github.com/prysmaticlabs/prysm/v4/config/features"
fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams"
consensus_types "github.com/prysmaticlabs/prysm/v4/consensus-types"
ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
)
@@ -26,15 +26,22 @@ func (b *BeaconState) SetBlockRoots(val [][]byte) error {
b.lock.Lock()
defer b.lock.Unlock()
b.sharedFieldReferences[types.BlockRoots].MinusRef()
b.sharedFieldReferences[types.BlockRoots] = stateutil.NewRef(1)
if features.Get().EnableExperimentalState {
if b.blockRootsMultiValue != nil {
b.blockRootsMultiValue.Detach(b)
}
b.blockRootsMultiValue = NewMultiValueBlockRoots(val)
} else {
b.sharedFieldReferences[types.BlockRoots].MinusRef()
b.sharedFieldReferences[types.BlockRoots] = stateutil.NewRef(1)
var rootsArr [fieldparams.BlockRootsLength][32]byte
for i := 0; i < len(rootsArr); i++ {
copy(rootsArr[i][:], val[i])
rootsArr := make([][32]byte, fieldparams.BlockRootsLength)
for i := 0; i < len(rootsArr); i++ {
copy(rootsArr[i][:], val[i])
}
b.blockRoots = rootsArr
}
roots := customtypes.BlockRoots(rootsArr)
b.blockRoots = &roots
b.markFieldAsDirty(types.BlockRoots)
b.rebuildTrie[types.BlockRoots] = true
return nil
@@ -43,24 +50,29 @@ 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 uint64(len(b.blockRoots)) <= idx {
return fmt.Errorf("invalid index provided %d", idx)
}
b.lock.Lock()
defer b.lock.Unlock()
r := b.blockRoots
if ref := b.sharedFieldReferences[types.BlockRoots]; ref.Refs() > 1 {
// Copy elements in underlying array by reference.
roots := *b.blockRoots
rootsCopy := roots
r = &rootsCopy
ref.MinusRef()
b.sharedFieldReferences[types.BlockRoots] = stateutil.NewRef(1)
}
if features.Get().EnableExperimentalState {
if err := b.blockRootsMultiValue.UpdateAt(b, idx, blockRoot); err != nil {
return errors.Wrap(err, "could not update block roots")
}
} else {
if uint64(len(b.blockRoots)) <= idx {
return errors.Wrapf(consensus_types.ErrOutOfBounds, "block root index %d does not exist", idx)
}
r[idx] = blockRoot
b.blockRoots = r
r := b.blockRoots
if ref := b.sharedFieldReferences[types.BlockRoots]; ref.Refs() > 1 {
// Copy elements in underlying array by reference.
r = make([][32]byte, len(b.blockRoots))
copy(r, b.blockRoots)
ref.MinusRef()
b.sharedFieldReferences[types.BlockRoots] = stateutil.NewRef(1)
}
r[idx] = blockRoot
b.blockRoots = r
}
b.markFieldAsDirty(types.BlockRoots)
b.addDirtyIndices(types.BlockRoots, []uint64{idx})

View File

@@ -2,11 +2,11 @@ package state_native
import (
"github.com/pkg/errors"
customtypes "github.com/prysmaticlabs/prysm/v4/beacon-chain/state/state-native/custom-types"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state/state-native/types"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state/stateutil"
"github.com/prysmaticlabs/prysm/v4/config/features"
fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams"
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
consensus_types "github.com/prysmaticlabs/prysm/v4/consensus-types"
)
// SetRandaoMixes for the beacon state. Updates the entire
@@ -15,15 +15,22 @@ func (b *BeaconState) SetRandaoMixes(val [][]byte) error {
b.lock.Lock()
defer b.lock.Unlock()
b.sharedFieldReferences[types.RandaoMixes].MinusRef()
b.sharedFieldReferences[types.RandaoMixes] = stateutil.NewRef(1)
if features.Get().EnableExperimentalState {
if b.randaoMixesMultiValue != nil {
b.randaoMixesMultiValue.Detach(b)
}
b.randaoMixesMultiValue = NewMultiValueRandaoMixes(val)
} else {
b.sharedFieldReferences[types.RandaoMixes].MinusRef()
b.sharedFieldReferences[types.RandaoMixes] = stateutil.NewRef(1)
var mixesArr [fieldparams.RandaoMixesLength][32]byte
for i := 0; i < len(mixesArr); i++ {
copy(mixesArr[i][:], val[i])
rootsArr := make([][32]byte, fieldparams.RandaoMixesLength)
for i := 0; i < len(rootsArr); i++ {
copy(rootsArr[i][:], val[i])
}
b.randaoMixes = rootsArr
}
mixes := customtypes.RandaoMixes(mixesArr)
b.randaoMixes = &mixes
b.markFieldAsDirty(types.RandaoMixes)
b.rebuildTrie[types.RandaoMixes] = true
return nil
@@ -31,27 +38,36 @@ 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 uint64(len(b.randaoMixes)) <= idx {
return errors.Errorf("invalid index provided %d", idx)
func (b *BeaconState) UpdateRandaoMixesAtIndex(idx uint64, val [32]byte) error {
if features.Get().EnableExperimentalState {
if err := b.randaoMixesMultiValue.UpdateAt(b, idx, val); err != nil {
return errors.Wrap(err, "could not update randao mixes")
}
} else {
if uint64(len(b.randaoMixes)) <= idx {
return errors.Wrapf(consensus_types.ErrOutOfBounds, "randao mix index %d does not exist", idx)
}
b.lock.Lock()
m := b.randaoMixes
if ref := b.sharedFieldReferences[types.RandaoMixes]; ref.Refs() > 1 {
// Copy elements in underlying array by reference.
m = make([][32]byte, len(b.randaoMixes))
copy(m, b.randaoMixes)
ref.MinusRef()
b.sharedFieldReferences[types.RandaoMixes] = stateutil.NewRef(1)
}
m[idx] = val
b.randaoMixes = m
b.lock.Unlock()
}
b.lock.Lock()
defer b.lock.Unlock()
mixes := b.randaoMixes
if refs := b.sharedFieldReferences[types.RandaoMixes].Refs(); refs > 1 {
// Copy elements in underlying array by reference.
m := *b.randaoMixes
mCopy := m
mixes = &mCopy
b.sharedFieldReferences[types.RandaoMixes].MinusRef()
b.sharedFieldReferences[types.RandaoMixes] = stateutil.NewRef(1)
}
mixes[idx] = bytesutil.ToBytes32(val)
b.randaoMixes = mixes
b.markFieldAsDirty(types.RandaoMixes)
b.addDirtyIndices(types.RandaoMixes, []uint64{idx})
return nil
}

View File

@@ -2,10 +2,11 @@ package state_native
import (
"github.com/pkg/errors"
customtypes "github.com/prysmaticlabs/prysm/v4/beacon-chain/state/state-native/custom-types"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state/state-native/types"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state/stateutil"
"github.com/prysmaticlabs/prysm/v4/config/features"
fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams"
consensus_types "github.com/prysmaticlabs/prysm/v4/consensus-types"
)
// SetStateRoots for the beacon state. Updates the state roots
@@ -14,15 +15,22 @@ func (b *BeaconState) SetStateRoots(val [][]byte) error {
b.lock.Lock()
defer b.lock.Unlock()
b.sharedFieldReferences[types.StateRoots].MinusRef()
b.sharedFieldReferences[types.StateRoots] = stateutil.NewRef(1)
if features.Get().EnableExperimentalState {
if b.stateRootsMultiValue != nil {
b.stateRootsMultiValue.Detach(b)
}
b.stateRootsMultiValue = NewMultiValueStateRoots(val)
} else {
b.sharedFieldReferences[types.StateRoots].MinusRef()
b.sharedFieldReferences[types.StateRoots] = stateutil.NewRef(1)
var rootsArr [fieldparams.StateRootsLength][32]byte
for i := 0; i < len(rootsArr); i++ {
copy(rootsArr[i][:], val[i])
rootsArr := make([][32]byte, fieldparams.StateRootsLength)
for i := 0; i < len(rootsArr); i++ {
copy(rootsArr[i][:], val[i])
}
b.stateRoots = rootsArr
}
roots := customtypes.StateRoots(rootsArr)
b.stateRoots = &roots
b.markFieldAsDirty(types.StateRoots)
b.rebuildTrie[types.StateRoots] = true
return nil
@@ -31,30 +39,34 @@ 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 {
b.lock.RLock()
if uint64(len(b.stateRoots)) <= idx {
b.lock.RUnlock()
return errors.Errorf("invalid index provided %d", idx)
if features.Get().EnableExperimentalState {
if err := b.stateRootsMultiValue.UpdateAt(b, idx, stateRoot); err != nil {
return errors.Wrap(err, "could not update state roots")
}
} else {
if uint64(len(b.stateRoots)) <= idx {
return errors.Wrapf(consensus_types.ErrOutOfBounds, "state root index %d does not exist", idx)
}
b.lock.Lock()
r := b.stateRoots
if ref := b.sharedFieldReferences[types.StateRoots]; ref.Refs() > 1 {
// Copy elements in underlying array by reference.
r = make([][32]byte, len(b.stateRoots))
copy(r, b.stateRoots)
ref.MinusRef()
b.sharedFieldReferences[types.StateRoots] = stateutil.NewRef(1)
}
r[idx] = stateRoot
b.stateRoots = r
b.lock.Unlock()
}
b.lock.RUnlock()
b.lock.Lock()
defer b.lock.Unlock()
// Check if we hold the only reference to the shared state roots slice.
r := b.stateRoots
if ref := b.sharedFieldReferences[types.StateRoots]; ref.Refs() > 1 {
// Copy elements in underlying array by reference.
roots := *b.stateRoots
rootsCopy := roots
r = &rootsCopy
ref.MinusRef()
b.sharedFieldReferences[types.StateRoots] = stateutil.NewRef(1)
}
r[idx] = stateRoot
b.stateRoots = r
b.markFieldAsDirty(types.StateRoots)
b.addDirtyIndices(types.StateRoots, []uint64{idx})
return nil

View File

@@ -4,6 +4,8 @@ import (
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state/state-native/types"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state/stateutil"
"github.com/prysmaticlabs/prysm/v4/config/features"
consensus_types "github.com/prysmaticlabs/prysm/v4/consensus-types"
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
@@ -16,69 +18,119 @@ func (b *BeaconState) SetValidators(val []*ethpb.Validator) error {
b.lock.Lock()
defer b.lock.Unlock()
b.validators = val
b.sharedFieldReferences[types.Validators].MinusRef()
b.sharedFieldReferences[types.Validators] = stateutil.NewRef(1)
if features.Get().EnableExperimentalState {
if b.validatorsMultiValue != nil {
b.validatorsMultiValue.Detach(b)
}
b.validatorsMultiValue = NewMultiValueValidators(val)
} else {
b.validators = val
b.sharedFieldReferences[types.Validators].MinusRef()
b.sharedFieldReferences[types.Validators] = stateutil.NewRef(1)
}
b.markFieldAsDirty(types.Validators)
b.rebuildTrie[types.Validators] = true
b.valMapHandler = stateutil.NewValMapHandler(b.validators)
b.valMapHandler = stateutil.NewValMapHandler(val)
return nil
}
// ApplyToEveryValidator applies the provided callback function to each validator in the
// validator registry.
func (b *BeaconState) ApplyToEveryValidator(f func(idx int, val *ethpb.Validator) (bool, *ethpb.Validator, error)) error {
b.lock.Lock()
v := b.validators
if ref := b.sharedFieldReferences[types.Validators]; ref.Refs() > 1 {
v = b.validatorsReferences()
ref.MinusRef()
b.sharedFieldReferences[types.Validators] = stateutil.NewRef(1)
}
b.lock.Unlock()
var changedVals []uint64
for i, val := range v {
changed, newVal, err := f(i, val)
if err != nil {
return err
if features.Get().EnableExperimentalState {
b.lock.Lock()
l := b.validatorsMultiValue.Len(b)
for i := 0; i < l; i++ {
v, err := b.validatorsMultiValue.At(b, uint64(i))
if err != nil {
b.lock.Unlock()
return err
}
changed, newVal, err := f(i, v)
if err != nil {
b.lock.Unlock()
return err
}
if changed {
changedVals = append(changedVals, uint64(i))
if err = b.validatorsMultiValue.UpdateAt(b, uint64(i), newVal); err != nil {
b.lock.Unlock()
return errors.Wrapf(err, "could not update validator at index %d", i)
}
}
}
if changed {
changedVals = append(changedVals, uint64(i))
v[i] = newVal
b.lock.Unlock()
} else {
b.lock.Lock()
v := b.validators
if ref := b.sharedFieldReferences[types.Validators]; ref.Refs() > 1 {
v = b.validatorsReferences()
ref.MinusRef()
b.sharedFieldReferences[types.Validators] = stateutil.NewRef(1)
}
b.lock.Unlock()
for i, val := range v {
changed, newVal, err := f(i, val)
if err != nil {
return err
}
if changed {
changedVals = append(changedVals, uint64(i))
v[i] = newVal
}
}
b.lock.Lock()
b.validators = v
b.lock.Unlock()
}
b.lock.Lock()
defer b.lock.Unlock()
b.validators = v
b.markFieldAsDirty(types.Validators)
b.addDirtyIndices(types.Validators, changedVals)
return nil
}
// UpdateValidatorAtIndex for the beacon state. Updates the validator
// at a specific index to a new value.
func (b *BeaconState) UpdateValidatorAtIndex(idx primitives.ValidatorIndex, val *ethpb.Validator) error {
if uint64(len(b.validators)) <= uint64(idx) {
return errors.Errorf("invalid index provided %d", idx)
if features.Get().EnableExperimentalState {
if err := b.validatorsMultiValue.UpdateAt(b, uint64(idx), val); err != nil {
return errors.Wrap(err, "could not update validator")
}
} else {
if uint64(len(b.validators)) <= uint64(idx) {
return errors.Wrapf(consensus_types.ErrOutOfBounds, "validator index %d does not exist", idx)
}
b.lock.Lock()
v := b.validators
if ref := b.sharedFieldReferences[types.Validators]; ref.Refs() > 1 {
v = b.validatorsReferences()
ref.MinusRef()
b.sharedFieldReferences[types.Validators] = stateutil.NewRef(1)
}
v[idx] = val
b.validators = v
b.lock.Unlock()
}
b.lock.Lock()
defer b.lock.Unlock()
v := b.validators
if ref := b.sharedFieldReferences[types.Validators]; ref.Refs() > 1 {
v = b.validatorsReferences()
ref.MinusRef()
b.sharedFieldReferences[types.Validators] = stateutil.NewRef(1)
}
v[idx] = val
b.validators = v
b.markFieldAsDirty(types.Validators)
b.addDirtyIndices(types.Validators, []uint64{uint64(idx)})
return nil
}
@@ -88,10 +140,17 @@ func (b *BeaconState) SetBalances(val []uint64) error {
b.lock.Lock()
defer b.lock.Unlock()
b.sharedFieldReferences[types.Balances].MinusRef()
b.sharedFieldReferences[types.Balances] = stateutil.NewRef(1)
if features.Get().EnableExperimentalState {
if b.balancesMultiValue != nil {
b.balancesMultiValue.Detach(b)
}
b.balancesMultiValue = NewMultiValueBalances(val)
} else {
b.sharedFieldReferences[types.Balances].MinusRef()
b.sharedFieldReferences[types.Balances] = stateutil.NewRef(1)
b.balances = val
}
b.balances = val
b.markFieldAsDirty(types.Balances)
b.rebuildTrie[types.Balances] = true
return nil
@@ -100,21 +159,32 @@ func (b *BeaconState) SetBalances(val []uint64) error {
// UpdateBalancesAtIndex for the beacon state. This method updates the balance
// at a specific index to a new value.
func (b *BeaconState) UpdateBalancesAtIndex(idx primitives.ValidatorIndex, val uint64) error {
if uint64(len(b.balances)) <= uint64(idx) {
return errors.Errorf("invalid index provided %d", idx)
if features.Get().EnableExperimentalState {
if err := b.balancesMultiValue.UpdateAt(b, uint64(idx), val); err != nil {
return errors.Wrap(err, "could not update balances")
}
} else {
if uint64(len(b.balances)) <= uint64(idx) {
return errors.Wrapf(consensus_types.ErrOutOfBounds, "balance index %d does not exist", idx)
}
b.lock.Lock()
bals := b.balances
if b.sharedFieldReferences[types.Balances].Refs() > 1 {
bals = b.balancesVal()
b.sharedFieldReferences[types.Balances].MinusRef()
b.sharedFieldReferences[types.Balances] = stateutil.NewRef(1)
}
bals[idx] = val
b.balances = bals
b.lock.Unlock()
}
b.lock.Lock()
defer b.lock.Unlock()
bals := b.balances
if b.sharedFieldReferences[types.Balances].Refs() > 1 {
bals = b.balancesVal()
b.sharedFieldReferences[types.Balances].MinusRef()
b.sharedFieldReferences[types.Balances] = stateutil.NewRef(1)
}
bals[idx] = val
b.balances = bals
b.markFieldAsDirty(types.Balances)
b.addDirtyIndices(types.Balances, []uint64{uint64(idx)})
return nil
@@ -161,22 +231,30 @@ func (b *BeaconState) UpdateSlashingsAtIndex(idx, val uint64) error {
// AppendValidator for the beacon state. Appends the new value
// to the end of list.
func (b *BeaconState) AppendValidator(val *ethpb.Validator) error {
var valIdx primitives.ValidatorIndex
if features.Get().EnableExperimentalState {
b.validatorsMultiValue.Append(b, val)
valIdx = primitives.ValidatorIndex(b.validatorsMultiValue.Len(b) - 1)
} else {
b.lock.Lock()
vals := b.validators
if b.sharedFieldReferences[types.Validators].Refs() > 1 {
vals = b.validatorsReferences()
b.sharedFieldReferences[types.Validators].MinusRef()
b.sharedFieldReferences[types.Validators] = stateutil.NewRef(1)
}
b.validators = append(vals, val)
valIdx = primitives.ValidatorIndex(len(b.validators) - 1)
b.lock.Unlock()
}
b.lock.Lock()
defer b.lock.Unlock()
vals := b.validators
if b.sharedFieldReferences[types.Validators].Refs() > 1 {
vals = b.validatorsReferences()
b.sharedFieldReferences[types.Validators].MinusRef()
b.sharedFieldReferences[types.Validators] = stateutil.NewRef(1)
}
// append validator to slice
b.validators = append(vals, val)
valIdx := primitives.ValidatorIndex(len(b.validators) - 1)
b.valMapHandler.Set(bytesutil.ToBytes48(val.PublicKey), valIdx)
b.markFieldAsDirty(types.Validators)
b.addDirtyIndices(types.Validators, []uint64{uint64(valIdx)})
return nil
@@ -185,42 +263,61 @@ func (b *BeaconState) AppendValidator(val *ethpb.Validator) error {
// AppendBalance for the beacon state. Appends the new value
// to the end of list.
func (b *BeaconState) AppendBalance(bal uint64) error {
var balIdx uint64
if features.Get().EnableExperimentalState {
b.balancesMultiValue.Append(b, bal)
balIdx = uint64(b.balancesMultiValue.Len(b) - 1)
} else {
b.lock.Lock()
bals := b.balances
if b.sharedFieldReferences[types.Balances].Refs() > 1 {
bals = make([]uint64, 0, len(b.balances)+1)
bals = append(bals, b.balances...)
b.sharedFieldReferences[types.Balances].MinusRef()
b.sharedFieldReferences[types.Balances] = stateutil.NewRef(1)
}
b.balances = append(bals, bal)
balIdx = uint64(len(b.balances) - 1)
b.lock.Unlock()
}
b.lock.Lock()
defer b.lock.Unlock()
bals := b.balances
if b.sharedFieldReferences[types.Balances].Refs() > 1 {
bals = make([]uint64, 0, len(b.balances)+1)
bals = append(bals, b.balances...)
b.sharedFieldReferences[types.Balances].MinusRef()
b.sharedFieldReferences[types.Balances] = stateutil.NewRef(1)
}
b.balances = append(bals, bal)
balIdx := len(b.balances) - 1
b.markFieldAsDirty(types.Balances)
b.addDirtyIndices(types.Balances, []uint64{uint64(balIdx)})
b.addDirtyIndices(types.Balances, []uint64{balIdx})
return nil
}
// AppendInactivityScore for the beacon state.
func (b *BeaconState) AppendInactivityScore(s uint64) error {
b.lock.Lock()
defer b.lock.Unlock()
if b.version == version.Phase0 {
return errNotSupported("AppendInactivityScore", b.version)
}
scores := b.inactivityScores
if b.sharedFieldReferences[types.InactivityScores].Refs() > 1 {
scores = make([]uint64, 0, len(b.inactivityScores)+1)
scores = append(scores, b.inactivityScores...)
b.sharedFieldReferences[types.InactivityScores].MinusRef()
b.sharedFieldReferences[types.InactivityScores] = stateutil.NewRef(1)
if features.Get().EnableExperimentalState {
b.inactivityScoresMultiValue.Append(b, s)
} else {
b.lock.Lock()
scores := b.inactivityScores
if b.sharedFieldReferences[types.InactivityScores].Refs() > 1 {
scores = make([]uint64, 0, len(b.inactivityScores)+1)
scores = append(scores, b.inactivityScores...)
b.sharedFieldReferences[types.InactivityScores].MinusRef()
b.sharedFieldReferences[types.InactivityScores] = stateutil.NewRef(1)
}
b.inactivityScores = append(scores, s)
b.lock.Unlock()
}
b.inactivityScores = append(scores, s)
b.lock.Lock()
defer b.lock.Unlock()
b.markFieldAsDirty(types.InactivityScores)
return nil
}
@@ -235,10 +332,17 @@ func (b *BeaconState) SetInactivityScores(val []uint64) error {
return errNotSupported("SetInactivityScores", b.version)
}
b.sharedFieldReferences[types.InactivityScores].MinusRef()
b.sharedFieldReferences[types.InactivityScores] = stateutil.NewRef(1)
if features.Get().EnableExperimentalState {
if b.inactivityScoresMultiValue != nil {
b.inactivityScoresMultiValue.Detach(b)
}
b.inactivityScoresMultiValue = NewMultiValueInactivityScores(val)
} else {
b.sharedFieldReferences[types.InactivityScores].MinusRef()
b.sharedFieldReferences[types.InactivityScores] = stateutil.NewRef(1)
b.inactivityScores = val
}
b.inactivityScores = val
b.markFieldAsDirty(types.InactivityScores)
return nil
}

View File

@@ -11,6 +11,7 @@ import (
customtypes "github.com/prysmaticlabs/prysm/v4/beacon-chain/state/state-native/custom-types"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state/state-native/types"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state/stateutil"
"github.com/prysmaticlabs/prysm/v4/config/features"
fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams"
"github.com/prysmaticlabs/prysm/v4/config/params"
"github.com/prysmaticlabs/prysm/v4/container/slice"
@@ -92,11 +93,16 @@ var denebFields = append(
)
const (
phase0SharedFieldRefCount = 10
altairSharedFieldRefCount = 11
bellatrixSharedFieldRefCount = 12
capellaSharedFieldRefCount = 14
denebSharedFieldRefCount = 14
phase0SharedFieldRefCount = 10
altairSharedFieldRefCount = 11
bellatrixSharedFieldRefCount = 12
capellaSharedFieldRefCount = 14
denebSharedFieldRefCount = 14
experimentalStatePhase0SharedFieldRefCount = 5
experimentalStateAltairSharedFieldRefCount = 5
experimentalStateBellatrixSharedFieldRefCount = 6
experimentalStateCapellaSharedFieldRefCount = 8
experimentalStateDenebSharedFieldRefCount = 8
)
// InitializeFromProtoPhase0 the beacon state from a protobuf representation.
@@ -131,22 +137,10 @@ func InitializeFromProtoUnsafePhase0(st *ethpb.BeaconState) (state.BeaconState,
return nil, errors.New("received nil state")
}
var bRoots customtypes.BlockRoots
for i, r := range st.BlockRoots {
copy(bRoots[i][:], r)
}
var sRoots customtypes.StateRoots
for i, r := range st.StateRoots {
copy(sRoots[i][:], r)
}
hRoots := customtypes.HistoricalRoots(make([][32]byte, len(st.HistoricalRoots)))
for i, r := range st.HistoricalRoots {
copy(hRoots[i][:], r)
}
var mixes customtypes.RandaoMixes
for i, m := range st.RandaoMixes {
copy(mixes[i][:], m)
}
fieldCount := params.BeaconConfig().BeaconStateFieldCount
b := &BeaconState{
@@ -156,15 +150,10 @@ func InitializeFromProtoUnsafePhase0(st *ethpb.BeaconState) (state.BeaconState,
slot: st.Slot,
fork: st.Fork,
latestBlockHeader: st.LatestBlockHeader,
blockRoots: &bRoots,
stateRoots: &sRoots,
historicalRoots: hRoots,
eth1Data: st.Eth1Data,
eth1DataVotes: st.Eth1DataVotes,
eth1DepositIndex: st.Eth1DepositIndex,
validators: st.Validators,
balances: st.Balances,
randaoMixes: &mixes,
slashings: st.Slashings,
previousEpochAttestations: st.PreviousEpochAttestations,
currentEpochAttestations: st.CurrentEpochAttestations,
@@ -173,12 +162,45 @@ func InitializeFromProtoUnsafePhase0(st *ethpb.BeaconState) (state.BeaconState,
currentJustifiedCheckpoint: st.CurrentJustifiedCheckpoint,
finalizedCheckpoint: st.FinalizedCheckpoint,
dirtyFields: make(map[types.FieldIndex]bool, fieldCount),
dirtyIndices: make(map[types.FieldIndex][]uint64, fieldCount),
stateFieldLeaves: make(map[types.FieldIndex]*fieldtrie.FieldTrie, fieldCount),
sharedFieldReferences: make(map[types.FieldIndex]*stateutil.Reference, phase0SharedFieldRefCount),
rebuildTrie: make(map[types.FieldIndex]bool, fieldCount),
valMapHandler: stateutil.NewValMapHandler(st.Validators),
id: types.Enumerator.Inc(),
dirtyFields: make(map[types.FieldIndex]bool, fieldCount),
dirtyIndices: make(map[types.FieldIndex][]uint64, fieldCount),
stateFieldLeaves: make(map[types.FieldIndex]*fieldtrie.FieldTrie, fieldCount),
rebuildTrie: make(map[types.FieldIndex]bool, fieldCount),
valMapHandler: stateutil.NewValMapHandler(st.Validators),
}
if features.Get().EnableExperimentalState {
b.blockRootsMultiValue = NewMultiValueBlockRoots(st.BlockRoots)
b.stateRootsMultiValue = NewMultiValueStateRoots(st.StateRoots)
b.randaoMixesMultiValue = NewMultiValueRandaoMixes(st.RandaoMixes)
b.balancesMultiValue = NewMultiValueBalances(st.Balances)
b.validatorsMultiValue = NewMultiValueValidators(st.Validators)
b.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, experimentalStatePhase0SharedFieldRefCount)
} else {
bRoots := make([][32]byte, fieldparams.BlockRootsLength)
for i, r := range st.BlockRoots {
bRoots[i] = bytesutil.ToBytes32(r)
}
b.blockRoots = bRoots
sRoots := make([][32]byte, fieldparams.StateRootsLength)
for i, r := range st.StateRoots {
sRoots[i] = bytesutil.ToBytes32(r)
}
b.stateRoots = sRoots
mixes := make([][32]byte, fieldparams.RandaoMixesLength)
for i, m := range st.RandaoMixes {
mixes[i] = bytesutil.ToBytes32(m)
}
b.randaoMixes = mixes
b.balances = st.Balances
b.validators = st.Validators
b.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, phase0SharedFieldRefCount)
}
for _, f := range phase0Fields {
@@ -193,16 +215,18 @@ func InitializeFromProtoUnsafePhase0(st *ethpb.BeaconState) (state.BeaconState,
}
// Initialize field reference tracking for shared data.
b.sharedFieldReferences[types.BlockRoots] = stateutil.NewRef(1)
b.sharedFieldReferences[types.StateRoots] = stateutil.NewRef(1)
b.sharedFieldReferences[types.HistoricalRoots] = stateutil.NewRef(1)
b.sharedFieldReferences[types.Eth1DataVotes] = stateutil.NewRef(1)
b.sharedFieldReferences[types.Validators] = stateutil.NewRef(1)
b.sharedFieldReferences[types.Balances] = stateutil.NewRef(1)
b.sharedFieldReferences[types.RandaoMixes] = stateutil.NewRef(1)
b.sharedFieldReferences[types.Slashings] = stateutil.NewRef(1)
b.sharedFieldReferences[types.PreviousEpochAttestations] = stateutil.NewRef(1)
b.sharedFieldReferences[types.CurrentEpochAttestations] = stateutil.NewRef(1)
if !features.Get().EnableExperimentalState {
b.sharedFieldReferences[types.BlockRoots] = stateutil.NewRef(1)
b.sharedFieldReferences[types.StateRoots] = stateutil.NewRef(1)
b.sharedFieldReferences[types.RandaoMixes] = stateutil.NewRef(1)
b.sharedFieldReferences[types.Balances] = stateutil.NewRef(1)
b.sharedFieldReferences[types.Validators] = stateutil.NewRef(1)
}
state.StateCount.Inc()
// Finalizer runs when dst is being destroyed in garbage collection.
@@ -217,22 +241,10 @@ func InitializeFromProtoUnsafeAltair(st *ethpb.BeaconStateAltair) (state.BeaconS
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{
@@ -242,15 +254,10 @@ func InitializeFromProtoUnsafeAltair(st *ethpb.BeaconStateAltair) (state.BeaconS
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,
@@ -258,16 +265,50 @@ func InitializeFromProtoUnsafeAltair(st *ethpb.BeaconStateAltair) (state.BeaconS
previousJustifiedCheckpoint: st.PreviousJustifiedCheckpoint,
currentJustifiedCheckpoint: st.CurrentJustifiedCheckpoint,
finalizedCheckpoint: st.FinalizedCheckpoint,
inactivityScores: st.InactivityScores,
currentSyncCommittee: st.CurrentSyncCommittee,
nextSyncCommittee: st.NextSyncCommittee,
dirtyFields: make(map[types.FieldIndex]bool, fieldCount),
dirtyIndices: make(map[types.FieldIndex][]uint64, fieldCount),
stateFieldLeaves: make(map[types.FieldIndex]*fieldtrie.FieldTrie, fieldCount),
sharedFieldReferences: make(map[types.FieldIndex]*stateutil.Reference, altairSharedFieldRefCount),
rebuildTrie: make(map[types.FieldIndex]bool, fieldCount),
valMapHandler: stateutil.NewValMapHandler(st.Validators),
id: types.Enumerator.Inc(),
dirtyFields: make(map[types.FieldIndex]bool, fieldCount),
dirtyIndices: make(map[types.FieldIndex][]uint64, fieldCount),
stateFieldLeaves: make(map[types.FieldIndex]*fieldtrie.FieldTrie, fieldCount),
rebuildTrie: make(map[types.FieldIndex]bool, fieldCount),
valMapHandler: stateutil.NewValMapHandler(st.Validators),
}
if features.Get().EnableExperimentalState {
b.blockRootsMultiValue = NewMultiValueBlockRoots(st.BlockRoots)
b.stateRootsMultiValue = NewMultiValueStateRoots(st.StateRoots)
b.randaoMixesMultiValue = NewMultiValueRandaoMixes(st.RandaoMixes)
b.balancesMultiValue = NewMultiValueBalances(st.Balances)
b.validatorsMultiValue = NewMultiValueValidators(st.Validators)
b.inactivityScoresMultiValue = NewMultiValueInactivityScores(st.InactivityScores)
b.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, experimentalStateAltairSharedFieldRefCount)
} else {
bRoots := make([][32]byte, fieldparams.BlockRootsLength)
for i, r := range st.BlockRoots {
bRoots[i] = bytesutil.ToBytes32(r)
}
b.blockRoots = bRoots
sRoots := make([][32]byte, fieldparams.StateRootsLength)
for i, r := range st.StateRoots {
sRoots[i] = bytesutil.ToBytes32(r)
}
b.stateRoots = sRoots
mixes := make([][32]byte, fieldparams.RandaoMixesLength)
for i, m := range st.RandaoMixes {
mixes[i] = bytesutil.ToBytes32(m)
}
b.randaoMixes = mixes
b.balances = st.Balances
b.validators = st.Validators
b.inactivityScores = st.InactivityScores
b.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, altairSharedFieldRefCount)
}
for _, f := range altairFields {
@@ -282,17 +323,19 @@ func InitializeFromProtoUnsafeAltair(st *ethpb.BeaconStateAltair) (state.BeaconS
}
// Initialize field reference tracking for shared data.
b.sharedFieldReferences[types.BlockRoots] = stateutil.NewRef(1)
b.sharedFieldReferences[types.StateRoots] = stateutil.NewRef(1)
b.sharedFieldReferences[types.HistoricalRoots] = stateutil.NewRef(1)
b.sharedFieldReferences[types.Eth1DataVotes] = stateutil.NewRef(1)
b.sharedFieldReferences[types.Validators] = stateutil.NewRef(1)
b.sharedFieldReferences[types.Balances] = stateutil.NewRef(1)
b.sharedFieldReferences[types.RandaoMixes] = stateutil.NewRef(1)
b.sharedFieldReferences[types.Slashings] = stateutil.NewRef(1)
b.sharedFieldReferences[types.PreviousEpochParticipationBits] = stateutil.NewRef(1) // New in Altair.
b.sharedFieldReferences[types.CurrentEpochParticipationBits] = stateutil.NewRef(1) // New in Altair.
b.sharedFieldReferences[types.InactivityScores] = stateutil.NewRef(1) // New in Altair.
if !features.Get().EnableExperimentalState {
b.sharedFieldReferences[types.BlockRoots] = stateutil.NewRef(1)
b.sharedFieldReferences[types.StateRoots] = stateutil.NewRef(1)
b.sharedFieldReferences[types.RandaoMixes] = stateutil.NewRef(1)
b.sharedFieldReferences[types.Balances] = stateutil.NewRef(1)
b.sharedFieldReferences[types.Validators] = stateutil.NewRef(1)
b.sharedFieldReferences[types.InactivityScores] = stateutil.NewRef(1)
}
state.StateCount.Inc()
// Finalizer runs when dst is being destroyed in garbage collection.
@@ -307,22 +350,10 @@ func InitializeFromProtoUnsafeBellatrix(st *ethpb.BeaconStateBellatrix) (state.B
return nil, errors.New("received nil state")
}
var bRoots customtypes.BlockRoots
for i, r := range st.BlockRoots {
bRoots[i] = bytesutil.ToBytes32(r)
}
var sRoots customtypes.StateRoots
for i, r := range st.StateRoots {
sRoots[i] = bytesutil.ToBytes32(r)
}
hRoots := customtypes.HistoricalRoots(make([][32]byte, len(st.HistoricalRoots)))
for i, r := range st.HistoricalRoots {
hRoots[i] = bytesutil.ToBytes32(r)
}
var mixes customtypes.RandaoMixes
for i, m := range st.RandaoMixes {
mixes[i] = bytesutil.ToBytes32(m)
}
fieldCount := params.BeaconConfig().BeaconStateBellatrixFieldCount
b := &BeaconState{
@@ -332,15 +363,10 @@ func InitializeFromProtoUnsafeBellatrix(st *ethpb.BeaconStateBellatrix) (state.B
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,
@@ -348,17 +374,51 @@ func InitializeFromProtoUnsafeBellatrix(st *ethpb.BeaconStateBellatrix) (state.B
previousJustifiedCheckpoint: st.PreviousJustifiedCheckpoint,
currentJustifiedCheckpoint: st.CurrentJustifiedCheckpoint,
finalizedCheckpoint: st.FinalizedCheckpoint,
inactivityScores: st.InactivityScores,
currentSyncCommittee: st.CurrentSyncCommittee,
nextSyncCommittee: st.NextSyncCommittee,
latestExecutionPayloadHeader: st.LatestExecutionPayloadHeader,
dirtyFields: make(map[types.FieldIndex]bool, fieldCount),
dirtyIndices: make(map[types.FieldIndex][]uint64, fieldCount),
stateFieldLeaves: make(map[types.FieldIndex]*fieldtrie.FieldTrie, fieldCount),
sharedFieldReferences: make(map[types.FieldIndex]*stateutil.Reference, bellatrixSharedFieldRefCount),
rebuildTrie: make(map[types.FieldIndex]bool, fieldCount),
valMapHandler: stateutil.NewValMapHandler(st.Validators),
id: types.Enumerator.Inc(),
dirtyFields: make(map[types.FieldIndex]bool, fieldCount),
dirtyIndices: make(map[types.FieldIndex][]uint64, fieldCount),
stateFieldLeaves: make(map[types.FieldIndex]*fieldtrie.FieldTrie, fieldCount),
rebuildTrie: make(map[types.FieldIndex]bool, fieldCount),
valMapHandler: stateutil.NewValMapHandler(st.Validators),
}
if features.Get().EnableExperimentalState {
b.blockRootsMultiValue = NewMultiValueBlockRoots(st.BlockRoots)
b.stateRootsMultiValue = NewMultiValueStateRoots(st.StateRoots)
b.randaoMixesMultiValue = NewMultiValueRandaoMixes(st.RandaoMixes)
b.balancesMultiValue = NewMultiValueBalances(st.Balances)
b.validatorsMultiValue = NewMultiValueValidators(st.Validators)
b.inactivityScoresMultiValue = NewMultiValueInactivityScores(st.InactivityScores)
b.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, experimentalStateBellatrixSharedFieldRefCount)
} else {
bRoots := make([][32]byte, fieldparams.BlockRootsLength)
for i, r := range st.BlockRoots {
bRoots[i] = bytesutil.ToBytes32(r)
}
b.blockRoots = bRoots
sRoots := make([][32]byte, fieldparams.StateRootsLength)
for i, r := range st.StateRoots {
sRoots[i] = bytesutil.ToBytes32(r)
}
b.stateRoots = sRoots
mixes := make([][32]byte, fieldparams.RandaoMixesLength)
for i, m := range st.RandaoMixes {
mixes[i] = bytesutil.ToBytes32(m)
}
b.randaoMixes = mixes
b.balances = st.Balances
b.validators = st.Validators
b.inactivityScores = st.InactivityScores
b.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, bellatrixSharedFieldRefCount)
}
for _, f := range bellatrixFields {
@@ -373,18 +433,20 @@ func InitializeFromProtoUnsafeBellatrix(st *ethpb.BeaconStateBellatrix) (state.B
}
// Initialize field reference tracking for shared data.
b.sharedFieldReferences[types.BlockRoots] = stateutil.NewRef(1)
b.sharedFieldReferences[types.StateRoots] = stateutil.NewRef(1)
b.sharedFieldReferences[types.HistoricalRoots] = stateutil.NewRef(1)
b.sharedFieldReferences[types.Eth1DataVotes] = stateutil.NewRef(1)
b.sharedFieldReferences[types.Validators] = stateutil.NewRef(1)
b.sharedFieldReferences[types.Balances] = stateutil.NewRef(1)
b.sharedFieldReferences[types.RandaoMixes] = stateutil.NewRef(1)
b.sharedFieldReferences[types.Slashings] = stateutil.NewRef(1)
b.sharedFieldReferences[types.PreviousEpochParticipationBits] = stateutil.NewRef(1)
b.sharedFieldReferences[types.CurrentEpochParticipationBits] = stateutil.NewRef(1)
b.sharedFieldReferences[types.InactivityScores] = stateutil.NewRef(1)
b.sharedFieldReferences[types.LatestExecutionPayloadHeader] = stateutil.NewRef(1) // New in Bellatrix.
if !features.Get().EnableExperimentalState {
b.sharedFieldReferences[types.BlockRoots] = stateutil.NewRef(1)
b.sharedFieldReferences[types.StateRoots] = stateutil.NewRef(1)
b.sharedFieldReferences[types.RandaoMixes] = stateutil.NewRef(1)
b.sharedFieldReferences[types.Balances] = stateutil.NewRef(1)
b.sharedFieldReferences[types.Validators] = stateutil.NewRef(1)
b.sharedFieldReferences[types.InactivityScores] = stateutil.NewRef(1)
}
state.StateCount.Inc()
// Finalizer runs when dst is being destroyed in garbage collection.
@@ -399,22 +461,10 @@ func InitializeFromProtoUnsafeCapella(st *ethpb.BeaconStateCapella) (state.Beaco
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().BeaconStateCapellaFieldCount
b := &BeaconState{
@@ -424,15 +474,10 @@ func InitializeFromProtoUnsafeCapella(st *ethpb.BeaconStateCapella) (state.Beaco
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,
@@ -440,7 +485,6 @@ func InitializeFromProtoUnsafeCapella(st *ethpb.BeaconStateCapella) (state.Beaco
previousJustifiedCheckpoint: st.PreviousJustifiedCheckpoint,
currentJustifiedCheckpoint: st.CurrentJustifiedCheckpoint,
finalizedCheckpoint: st.FinalizedCheckpoint,
inactivityScores: st.InactivityScores,
currentSyncCommittee: st.CurrentSyncCommittee,
nextSyncCommittee: st.NextSyncCommittee,
latestExecutionPayloadHeaderCapella: st.LatestExecutionPayloadHeader,
@@ -448,12 +492,47 @@ func InitializeFromProtoUnsafeCapella(st *ethpb.BeaconStateCapella) (state.Beaco
nextWithdrawalValidatorIndex: st.NextWithdrawalValidatorIndex,
historicalSummaries: st.HistoricalSummaries,
dirtyFields: make(map[types.FieldIndex]bool, fieldCount),
dirtyIndices: make(map[types.FieldIndex][]uint64, fieldCount),
stateFieldLeaves: make(map[types.FieldIndex]*fieldtrie.FieldTrie, fieldCount),
sharedFieldReferences: make(map[types.FieldIndex]*stateutil.Reference, capellaSharedFieldRefCount),
rebuildTrie: make(map[types.FieldIndex]bool, fieldCount),
valMapHandler: stateutil.NewValMapHandler(st.Validators),
id: types.Enumerator.Inc(),
dirtyFields: make(map[types.FieldIndex]bool, fieldCount),
dirtyIndices: make(map[types.FieldIndex][]uint64, fieldCount),
stateFieldLeaves: make(map[types.FieldIndex]*fieldtrie.FieldTrie, fieldCount),
rebuildTrie: make(map[types.FieldIndex]bool, fieldCount),
valMapHandler: stateutil.NewValMapHandler(st.Validators),
}
if features.Get().EnableExperimentalState {
b.blockRootsMultiValue = NewMultiValueBlockRoots(st.BlockRoots)
b.stateRootsMultiValue = NewMultiValueStateRoots(st.StateRoots)
b.randaoMixesMultiValue = NewMultiValueRandaoMixes(st.RandaoMixes)
b.balancesMultiValue = NewMultiValueBalances(st.Balances)
b.validatorsMultiValue = NewMultiValueValidators(st.Validators)
b.inactivityScoresMultiValue = NewMultiValueInactivityScores(st.InactivityScores)
b.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, experimentalStateCapellaSharedFieldRefCount)
} else {
bRoots := make([][32]byte, fieldparams.BlockRootsLength)
for i, r := range st.BlockRoots {
bRoots[i] = bytesutil.ToBytes32(r)
}
b.blockRoots = bRoots
sRoots := make([][32]byte, fieldparams.StateRootsLength)
for i, r := range st.StateRoots {
sRoots[i] = bytesutil.ToBytes32(r)
}
b.stateRoots = sRoots
mixes := make([][32]byte, fieldparams.RandaoMixesLength)
for i, m := range st.RandaoMixes {
mixes[i] = bytesutil.ToBytes32(m)
}
b.randaoMixes = mixes
b.balances = st.Balances
b.validators = st.Validators
b.inactivityScores = st.InactivityScores
b.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, capellaSharedFieldRefCount)
}
for _, f := range capellaFields {
@@ -468,19 +547,21 @@ func InitializeFromProtoUnsafeCapella(st *ethpb.BeaconStateCapella) (state.Beaco
}
// Initialize field reference tracking for shared data.
b.sharedFieldReferences[types.BlockRoots] = stateutil.NewRef(1)
b.sharedFieldReferences[types.StateRoots] = stateutil.NewRef(1)
b.sharedFieldReferences[types.HistoricalRoots] = stateutil.NewRef(1)
b.sharedFieldReferences[types.Eth1DataVotes] = stateutil.NewRef(1)
b.sharedFieldReferences[types.Validators] = stateutil.NewRef(1)
b.sharedFieldReferences[types.Balances] = stateutil.NewRef(1)
b.sharedFieldReferences[types.RandaoMixes] = stateutil.NewRef(1)
b.sharedFieldReferences[types.Slashings] = stateutil.NewRef(1)
b.sharedFieldReferences[types.PreviousEpochParticipationBits] = stateutil.NewRef(1)
b.sharedFieldReferences[types.CurrentEpochParticipationBits] = stateutil.NewRef(1)
b.sharedFieldReferences[types.InactivityScores] = stateutil.NewRef(1)
b.sharedFieldReferences[types.LatestExecutionPayloadHeaderCapella] = stateutil.NewRef(1) // New in Capella.
b.sharedFieldReferences[types.HistoricalSummaries] = stateutil.NewRef(1) // New in Capella.
if !features.Get().EnableExperimentalState {
b.sharedFieldReferences[types.BlockRoots] = stateutil.NewRef(1)
b.sharedFieldReferences[types.StateRoots] = stateutil.NewRef(1)
b.sharedFieldReferences[types.RandaoMixes] = stateutil.NewRef(1)
b.sharedFieldReferences[types.Balances] = stateutil.NewRef(1)
b.sharedFieldReferences[types.Validators] = stateutil.NewRef(1)
b.sharedFieldReferences[types.InactivityScores] = stateutil.NewRef(1)
}
state.StateCount.Inc()
// Finalizer runs when dst is being destroyed in garbage collection.
@@ -495,22 +576,10 @@ func InitializeFromProtoUnsafeDeneb(st *ethpb.BeaconStateDeneb) (state.BeaconSta
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().BeaconStateDenebFieldCount
b := &BeaconState{
@@ -520,15 +589,10 @@ func InitializeFromProtoUnsafeDeneb(st *ethpb.BeaconStateDeneb) (state.BeaconSta
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,
@@ -536,7 +600,6 @@ func InitializeFromProtoUnsafeDeneb(st *ethpb.BeaconStateDeneb) (state.BeaconSta
previousJustifiedCheckpoint: st.PreviousJustifiedCheckpoint,
currentJustifiedCheckpoint: st.CurrentJustifiedCheckpoint,
finalizedCheckpoint: st.FinalizedCheckpoint,
inactivityScores: st.InactivityScores,
currentSyncCommittee: st.CurrentSyncCommittee,
nextSyncCommittee: st.NextSyncCommittee,
latestExecutionPayloadHeaderDeneb: st.LatestExecutionPayloadHeader,
@@ -544,12 +607,45 @@ func InitializeFromProtoUnsafeDeneb(st *ethpb.BeaconStateDeneb) (state.BeaconSta
nextWithdrawalValidatorIndex: st.NextWithdrawalValidatorIndex,
historicalSummaries: st.HistoricalSummaries,
dirtyFields: make(map[types.FieldIndex]bool, fieldCount),
dirtyIndices: make(map[types.FieldIndex][]uint64, fieldCount),
stateFieldLeaves: make(map[types.FieldIndex]*fieldtrie.FieldTrie, fieldCount),
sharedFieldReferences: make(map[types.FieldIndex]*stateutil.Reference, capellaSharedFieldRefCount),
rebuildTrie: make(map[types.FieldIndex]bool, fieldCount),
valMapHandler: stateutil.NewValMapHandler(st.Validators),
dirtyFields: make(map[types.FieldIndex]bool, fieldCount),
dirtyIndices: make(map[types.FieldIndex][]uint64, fieldCount),
stateFieldLeaves: make(map[types.FieldIndex]*fieldtrie.FieldTrie, fieldCount),
rebuildTrie: make(map[types.FieldIndex]bool, fieldCount),
valMapHandler: stateutil.NewValMapHandler(st.Validators),
}
if features.Get().EnableExperimentalState {
b.blockRootsMultiValue = NewMultiValueBlockRoots(st.BlockRoots)
b.stateRootsMultiValue = NewMultiValueStateRoots(st.StateRoots)
b.randaoMixesMultiValue = NewMultiValueRandaoMixes(st.RandaoMixes)
b.balancesMultiValue = NewMultiValueBalances(st.Balances)
b.validatorsMultiValue = NewMultiValueValidators(st.Validators)
b.inactivityScoresMultiValue = NewMultiValueInactivityScores(st.InactivityScores)
b.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, experimentalStateDenebSharedFieldRefCount)
} else {
bRoots := make([][32]byte, fieldparams.BlockRootsLength)
for i, r := range st.BlockRoots {
bRoots[i] = bytesutil.ToBytes32(r)
}
b.blockRoots = bRoots
sRoots := make([][32]byte, fieldparams.StateRootsLength)
for i, r := range st.StateRoots {
sRoots[i] = bytesutil.ToBytes32(r)
}
b.stateRoots = sRoots
mixes := make([][32]byte, fieldparams.RandaoMixesLength)
for i, m := range st.RandaoMixes {
mixes[i] = bytesutil.ToBytes32(m)
}
b.randaoMixes = mixes
b.balances = st.Balances
b.validators = st.Validators
b.inactivityScores = st.InactivityScores
b.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, denebSharedFieldRefCount)
}
for _, f := range denebFields {
@@ -564,19 +660,21 @@ func InitializeFromProtoUnsafeDeneb(st *ethpb.BeaconStateDeneb) (state.BeaconSta
}
// Initialize field reference tracking for shared data.
b.sharedFieldReferences[types.BlockRoots] = stateutil.NewRef(1)
b.sharedFieldReferences[types.StateRoots] = stateutil.NewRef(1)
b.sharedFieldReferences[types.HistoricalRoots] = stateutil.NewRef(1)
b.sharedFieldReferences[types.Eth1DataVotes] = stateutil.NewRef(1)
b.sharedFieldReferences[types.Validators] = stateutil.NewRef(1)
b.sharedFieldReferences[types.Balances] = stateutil.NewRef(1)
b.sharedFieldReferences[types.RandaoMixes] = stateutil.NewRef(1)
b.sharedFieldReferences[types.Slashings] = stateutil.NewRef(1)
b.sharedFieldReferences[types.PreviousEpochParticipationBits] = stateutil.NewRef(1)
b.sharedFieldReferences[types.CurrentEpochParticipationBits] = stateutil.NewRef(1)
b.sharedFieldReferences[types.InactivityScores] = stateutil.NewRef(1)
b.sharedFieldReferences[types.LatestExecutionPayloadHeaderDeneb] = stateutil.NewRef(1) // New in Deneb.
b.sharedFieldReferences[types.HistoricalSummaries] = stateutil.NewRef(1) // New in Capella.
if !features.Get().EnableExperimentalState {
b.sharedFieldReferences[types.BlockRoots] = stateutil.NewRef(1)
b.sharedFieldReferences[types.StateRoots] = stateutil.NewRef(1)
b.sharedFieldReferences[types.RandaoMixes] = stateutil.NewRef(1)
b.sharedFieldReferences[types.Balances] = stateutil.NewRef(1)
b.sharedFieldReferences[types.Validators] = stateutil.NewRef(1)
b.sharedFieldReferences[types.InactivityScores] = stateutil.NewRef(1)
}
state.StateCount.Inc()
// Finalizer runs when dst is being destroyed in garbage collection.
@@ -615,8 +713,11 @@ func (b *BeaconState) Copy() state.BeaconState {
// Large arrays, infrequently changed, constant size.
blockRoots: b.blockRoots,
blockRootsMultiValue: b.blockRootsMultiValue,
stateRoots: b.stateRoots,
stateRootsMultiValue: b.stateRootsMultiValue,
randaoMixes: b.randaoMixes,
randaoMixesMultiValue: b.randaoMixesMultiValue,
previousEpochAttestations: b.previousEpochAttestations,
currentEpochAttestations: b.currentEpochAttestations,
eth1DataVotes: b.eth1DataVotes,
@@ -624,12 +725,15 @@ func (b *BeaconState) Copy() state.BeaconState {
// Large arrays, increases over time.
balances: b.balances,
balancesMultiValue: b.balancesMultiValue,
historicalRoots: b.historicalRoots,
historicalSummaries: b.historicalSummaries,
validators: b.validators,
validatorsMultiValue: b.validatorsMultiValue,
previousEpochParticipation: b.previousEpochParticipation,
currentEpochParticipation: b.currentEpochParticipation,
inactivityScores: b.inactivityScores,
inactivityScoresMultiValue: b.inactivityScoresMultiValue,
// Everything else, too small to be concerned about, constant size.
genesisValidatorsRoot: b.genesisValidatorsRoot,
@@ -646,6 +750,8 @@ func (b *BeaconState) Copy() state.BeaconState {
latestExecutionPayloadHeaderCapella: b.latestExecutionPayloadHeaderCapellaVal(),
latestExecutionPayloadHeaderDeneb: b.latestExecutionPayloadHeaderDenebVal(),
id: types.Enumerator.Inc(),
dirtyFields: make(map[types.FieldIndex]bool, fieldCount),
dirtyIndices: make(map[types.FieldIndex][]uint64, fieldCount),
rebuildTrie: make(map[types.FieldIndex]bool, fieldCount),
@@ -655,17 +761,43 @@ func (b *BeaconState) Copy() state.BeaconState {
valMapHandler: b.valMapHandler,
}
switch b.version {
case version.Phase0:
dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, phase0SharedFieldRefCount)
case version.Altair:
dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, altairSharedFieldRefCount)
case version.Bellatrix:
dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, bellatrixSharedFieldRefCount)
case version.Capella:
dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, capellaSharedFieldRefCount)
case version.Deneb:
dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, denebSharedFieldRefCount)
if features.Get().EnableExperimentalState {
b.blockRootsMultiValue.Copy(b, dst)
b.stateRootsMultiValue.Copy(b, dst)
b.randaoMixesMultiValue.Copy(b, dst)
b.balancesMultiValue.Copy(b, dst)
if b.version > version.Phase0 {
b.inactivityScoresMultiValue.Copy(b, dst)
}
b.validatorsMultiValue.Copy(b, dst)
}
if features.Get().EnableExperimentalState {
switch b.version {
case version.Phase0:
dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, experimentalStatePhase0SharedFieldRefCount)
case version.Altair:
dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, experimentalStateAltairSharedFieldRefCount)
case version.Bellatrix:
dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, experimentalStateBellatrixSharedFieldRefCount)
case version.Capella:
dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, experimentalStateCapellaSharedFieldRefCount)
case version.Deneb:
dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, experimentalStateDenebSharedFieldRefCount)
}
} else {
switch b.version {
case version.Phase0:
dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, phase0SharedFieldRefCount)
case version.Altair:
dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, altairSharedFieldRefCount)
case version.Bellatrix:
dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, bellatrixSharedFieldRefCount)
case version.Capella:
dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, capellaSharedFieldRefCount)
case version.Deneb:
dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, denebSharedFieldRefCount)
}
}
for field, ref := range b.sharedFieldReferences {
@@ -824,25 +956,9 @@ func (b *BeaconState) rootSelector(ctx context.Context, field types.FieldIndex)
case types.LatestBlockHeader:
return stateutil.BlockHeaderRoot(b.latestBlockHeader)
case types.BlockRoots:
if b.rebuildTrie[field] {
err := b.resetFieldTrie(field, b.blockRoots, fieldparams.BlockRootsLength)
if err != nil {
return [32]byte{}, err
}
delete(b.rebuildTrie, field)
return b.stateFieldLeaves[field].TrieRoot()
}
return b.recomputeFieldTrie(field, b.blockRoots)
return b.blockRootsRootSelector(field)
case types.StateRoots:
if b.rebuildTrie[field] {
err := b.resetFieldTrie(field, b.stateRoots, fieldparams.StateRootsLength)
if err != nil {
return [32]byte{}, err
}
delete(b.rebuildTrie, field)
return b.stateFieldLeaves[field].TrieRoot()
}
return b.recomputeFieldTrie(field, b.stateRoots)
return b.stateRootsRootSelector(field)
case types.HistoricalRoots:
hRoots := make([][]byte, len(b.historicalRoots))
for i := range hRoots {
@@ -866,35 +982,11 @@ func (b *BeaconState) rootSelector(ctx context.Context, field types.FieldIndex)
}
return b.recomputeFieldTrie(field, b.eth1DataVotes)
case types.Validators:
if b.rebuildTrie[field] {
err := b.resetFieldTrie(field, b.validators, fieldparams.ValidatorRegistryLimit)
if err != nil {
return [32]byte{}, err
}
delete(b.rebuildTrie, field)
return b.stateFieldLeaves[field].TrieRoot()
}
return b.recomputeFieldTrie(11, b.validators)
return b.validatorsRootSelector(field)
case types.Balances:
if b.rebuildTrie[field] {
err := b.resetFieldTrie(field, b.balances, stateutil.ValidatorLimitForBalancesChunks())
if err != nil {
return [32]byte{}, err
}
delete(b.rebuildTrie, field)
return b.stateFieldLeaves[field].TrieRoot()
}
return b.recomputeFieldTrie(12, b.balances)
return b.balancesRootSelector(field)
case types.RandaoMixes:
if b.rebuildTrie[field] {
err := b.resetFieldTrie(field, b.randaoMixes, fieldparams.RandaoMixesLength)
if err != nil {
return [32]byte{}, err
}
delete(b.rebuildTrie, field)
return b.stateFieldLeaves[field].TrieRoot()
}
return b.recomputeFieldTrie(13, b.randaoMixes)
return b.randaoMixesRootSelector(field)
case types.Slashings:
return ssz.SlashingsRoot(b.slashings)
case types.PreviousEpochAttestations:
@@ -938,7 +1030,11 @@ func (b *BeaconState) rootSelector(ctx context.Context, field types.FieldIndex)
case types.FinalizedCheckpoint:
return ssz.CheckpointRoot(b.finalizedCheckpoint)
case types.InactivityScores:
return stateutil.Uint64ListRootWithRegistryLimit(b.inactivityScores)
if features.Get().EnableExperimentalState {
return stateutil.Uint64ListRootWithRegistryLimit(b.inactivityScoresMultiValue.Value(b))
} else {
return stateutil.Uint64ListRootWithRegistryLimit(b.inactivityScores)
}
case types.CurrentSyncCommittee:
return stateutil.SyncCommitteeRoot(b.currentSyncCommittee)
case types.NextSyncCommittee:
@@ -1054,5 +1150,142 @@ func finalizerCleanup(b *BeaconState) {
for i := range b.stateFieldLeaves {
delete(b.stateFieldLeaves, i)
}
if features.Get().EnableExperimentalState {
if b.blockRootsMultiValue != nil {
b.blockRootsMultiValue.Detach(b)
}
if b.stateRootsMultiValue != nil {
b.stateRootsMultiValue.Detach(b)
}
if b.randaoMixesMultiValue != nil {
b.randaoMixesMultiValue.Detach(b)
}
if b.balancesMultiValue != nil {
b.balancesMultiValue.Detach(b)
}
if b.inactivityScoresMultiValue != nil {
b.inactivityScoresMultiValue.Detach(b)
}
if b.validatorsMultiValue != nil {
b.validatorsMultiValue.Detach(b)
}
}
state.StateCount.Sub(1)
}
func (b *BeaconState) blockRootsRootSelector(field types.FieldIndex) ([32]byte, error) {
if b.rebuildTrie[field] {
if features.Get().EnableExperimentalState {
err := b.resetFieldTrie(field, customtypes.BlockRoots(b.blockRootsMultiValue.Value(b)), fieldparams.BlockRootsLength)
if err != nil {
return [32]byte{}, err
}
} else {
err := b.resetFieldTrie(field, b.blockRoots, fieldparams.BlockRootsLength)
if err != nil {
return [32]byte{}, err
}
}
delete(b.rebuildTrie, field)
return b.stateFieldLeaves[field].TrieRoot()
}
if features.Get().EnableExperimentalState {
return b.recomputeFieldTrie(field, customtypes.BlockRoots(b.blockRootsMultiValue.Value(b)))
} else {
return b.recomputeFieldTrie(field, b.blockRoots)
}
}
func (b *BeaconState) stateRootsRootSelector(field types.FieldIndex) ([32]byte, error) {
if b.rebuildTrie[field] {
if features.Get().EnableExperimentalState {
err := b.resetFieldTrie(field, customtypes.StateRoots(b.stateRootsMultiValue.Value(b)), fieldparams.StateRootsLength)
if err != nil {
return [32]byte{}, err
}
} else {
err := b.resetFieldTrie(field, b.stateRoots, fieldparams.StateRootsLength)
if err != nil {
return [32]byte{}, err
}
}
delete(b.rebuildTrie, field)
return b.stateFieldLeaves[field].TrieRoot()
}
if features.Get().EnableExperimentalState {
return b.recomputeFieldTrie(field, customtypes.StateRoots(b.stateRootsMultiValue.Value(b)))
} else {
return b.recomputeFieldTrie(field, b.stateRoots)
}
}
func (b *BeaconState) validatorsRootSelector(field types.FieldIndex) ([32]byte, error) {
if b.rebuildTrie[field] {
if features.Get().EnableExperimentalState {
err := b.resetFieldTrie(field, b.validatorsMultiValue.Value(b), fieldparams.ValidatorRegistryLimit)
if err != nil {
return [32]byte{}, err
}
} else {
err := b.resetFieldTrie(field, b.validators, fieldparams.ValidatorRegistryLimit)
if err != nil {
return [32]byte{}, err
}
}
delete(b.rebuildTrie, field)
return b.stateFieldLeaves[field].TrieRoot()
}
if features.Get().EnableExperimentalState {
return b.recomputeFieldTrie(field, b.validatorsMultiValue.Value(b))
} else {
return b.recomputeFieldTrie(field, b.validators)
}
}
func (b *BeaconState) balancesRootSelector(field types.FieldIndex) ([32]byte, error) {
if b.rebuildTrie[field] {
if features.Get().EnableExperimentalState {
err := b.resetFieldTrie(field, b.balancesMultiValue.Value(b), stateutil.ValidatorLimitForBalancesChunks())
if err != nil {
return [32]byte{}, err
}
} else {
err := b.resetFieldTrie(field, b.balances, stateutil.ValidatorLimitForBalancesChunks())
if err != nil {
return [32]byte{}, err
}
}
delete(b.rebuildTrie, field)
return b.stateFieldLeaves[field].TrieRoot()
}
if features.Get().EnableExperimentalState {
return b.recomputeFieldTrie(field, b.balancesMultiValue.Value(b))
} else {
return b.recomputeFieldTrie(field, b.balances)
}
}
func (b *BeaconState) randaoMixesRootSelector(field types.FieldIndex) ([32]byte, error) {
if b.rebuildTrie[field] {
if features.Get().EnableExperimentalState {
err := b.resetFieldTrie(field, customtypes.RandaoMixes(b.randaoMixesMultiValue.Value(b)), fieldparams.RandaoMixesLength)
if err != nil {
return [32]byte{}, err
}
} else {
err := b.resetFieldTrie(field, b.randaoMixes, fieldparams.RandaoMixesLength)
if err != nil {
return [32]byte{}, err
}
}
delete(b.rebuildTrie, field)
return b.stateFieldLeaves[field].TrieRoot()
}
if features.Get().EnableExperimentalState {
return b.recomputeFieldTrie(field, customtypes.RandaoMixes(b.randaoMixesMultiValue.Value(b)))
} else {
return b.recomputeFieldTrie(field, b.randaoMixes)
}
}

View File

@@ -11,6 +11,7 @@ import (
// Ensure type BeaconState below implements BeaconState interface.
var _ state.BeaconState = (*BeaconState)(nil)
// initialization for tests
func init() {
fieldMap = make(map[types.FieldIndex]types.DataType)
// Initialize the fixed sized arrays.

View File

@@ -5,5 +5,8 @@ go_library(
srcs = ["types.go"],
importpath = "github.com/prysmaticlabs/prysm/v4/beacon-chain/state/state-native/types",
visibility = ["//visibility:public"],
deps = ["@com_github_pkg_errors//:go_default_library"],
deps = [
"//consensus-types:go_default_library",
"@com_github_pkg_errors//:go_default_library",
],
)

View File

@@ -2,6 +2,7 @@ package types
import (
"github.com/pkg/errors"
consensus_types "github.com/prysmaticlabs/prysm/v4/consensus-types"
)
// DataType signifies the data type of the field.
@@ -210,3 +211,6 @@ const (
NextWithdrawalValidatorIndex
HistoricalSummaries
)
// Enumerator keeps track of the number of states created since the node's start.
var Enumerator = &consensus_types.ThreadSafeEnumerator{}

View File

@@ -185,7 +185,7 @@ func TestBeaconState_ImmutabilityWithSharedResources(t *testing.T) {
// Randao mixes
require.DeepEqual(t, a.RandaoMixes(), b.RandaoMixes(), "Test precondition failed, fields are not equal")
require.NoError(t, a.UpdateRandaoMixesAtIndex(1, []byte("foo")))
require.NoError(t, a.UpdateRandaoMixesAtIndex(1, bytesutil.ToBytes32([]byte("foo"))))
if reflect.DeepEqual(a.RandaoMixes(), b.RandaoMixes()) {
t.Error("Expect a.RandaoMixes() to be different from b.RandaoMixes()")
}

View File

@@ -30,7 +30,13 @@ func TestMigrateToCold_CanSaveFinalizedInfo(t *testing.T) {
require.NoError(t, service.MigrateToCold(ctx, br))
wanted := &finalizedInfo{state: beaconState, root: br, slot: 1}
assert.DeepEqual(t, wanted, service.finalizedInfo, "Incorrect finalized info")
assert.DeepEqual(t, wanted.root, service.finalizedInfo.root)
assert.Equal(t, wanted.slot, service.finalizedInfo.slot)
expectedHTR, err := wanted.state.HashTreeRoot(ctx)
require.NoError(t, err)
actualHTR, err := service.finalizedInfo.state.HashTreeRoot(ctx)
require.NoError(t, err)
assert.DeepEqual(t, expectedHTR, actualHTR)
}
func TestMigrateToCold_HappyPath(t *testing.T) {

View File

@@ -34,12 +34,20 @@ func TestMockHistoryStates(t *testing.T) {
genesisRoot := hist.slotMap[0]
st, err := hist.StateOrError(ctx, genesisRoot)
require.NoError(t, err)
require.DeepEqual(t, hist.states[genesisRoot], st)
expectedHTR, err := hist.states[genesisRoot].HashTreeRoot(ctx)
require.NoError(t, err)
actualHTR, err := st.HashTreeRoot(ctx)
require.NoError(t, err)
require.DeepEqual(t, expectedHTR, actualHTR)
require.Equal(t, primitives.Slot(0), st.Slot())
shouldExist, err := hist.StateOrError(ctx, hist.slotMap[middle])
require.NoError(t, err)
require.DeepEqual(t, hist.states[hist.slotMap[middle]], shouldExist)
expectedHTR, err = hist.states[hist.slotMap[middle]].HashTreeRoot(ctx)
require.NoError(t, err)
actualHTR, err = shouldExist.HashTreeRoot(ctx)
require.NoError(t, err)
require.DeepEqual(t, expectedHTR, actualHTR)
require.Equal(t, middle, shouldExist.Slot())
cantExist, err := hist.StateOrError(ctx, hist.slotMap[end])

View File

@@ -37,6 +37,7 @@ const disabledFeatureFlag = "Disabled feature flag"
// Flags is a struct to represent which features the client will perform on runtime.
type Flags struct {
// Feature related flags.
EnableExperimentalState bool // EnableExperimentalState turns on the latest and greatest (but potentially unstable) changes to the beacon state.
WriteSSZStateTransitions bool // WriteSSZStateTransitions to tmp directory.
EnablePeerScorer bool // EnablePeerScorer enables experimental peer scoring in p2p.
DisableReorgLateBlocks bool // DisableReorgLateBlocks disables reorgs of late blocks.
@@ -176,6 +177,11 @@ func ConfigureBeaconChain(ctx *cli.Context) error {
return err
}
if ctx.Bool(enableExperimentalState.Name) {
logEnabled(enableExperimentalState)
cfg.EnableExperimentalState = true
}
if ctx.Bool(writeSSZStateTransitionsFlag.Name) {
logEnabled(writeSSZStateTransitionsFlag)
cfg.WriteSSZStateTransitions = true

View File

@@ -33,6 +33,10 @@ var (
Name: "dev",
Usage: "Enable experimental features still in development. These features may not be stable.",
}
enableExperimentalState = &cli.BoolFlag{
Name: "enable-experimental-state",
Usage: "Turn on the latest and greatest (but potentially unstable) changes to the beacon state",
}
writeSSZStateTransitionsFlag = &cli.BoolFlag{
Name: "interop-write-ssz-state-transitions",
Usage: "Write ssz states to disk after attempted state transition",
@@ -165,6 +169,7 @@ var (
var devModeFlags = []cli.Flag{
enableVerboseSigVerification,
enableEIP4881,
enableExperimentalState,
}
// ValidatorFlags contains a list of all the feature flags that apply to the validator client.
@@ -189,6 +194,7 @@ var E2EValidatorFlags = []string{
// BeaconChainFlags contains a list of all the feature flags that apply to the beacon-chain client.
var BeaconChainFlags = append(deprecatedBeaconFlags, append(deprecatedFlags, []cli.Flag{
devModeFlag,
enableExperimentalState,
writeSSZStateTransitionsFlag,
disableGRPCConnectionLogging,
HoleskyTestnet,

View File

@@ -3,6 +3,7 @@ package consensus_types
import (
"errors"
"fmt"
"sync/atomic"
errors2 "github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/v4/runtime/version"
@@ -13,9 +14,21 @@ var (
ErrNilObjectWrapped = errors.New("attempted to wrap nil object")
// ErrUnsupportedField is returned when a getter/setter access is not supported.
ErrUnsupportedField = errors.New("unsupported getter")
// ErrOutOfBounds is returned when a slice or array index does not exist.
ErrOutOfBounds = errors.New("index out of bounds")
)
// ErrNotSupported constructs a message informing about an unsupported field access.
func ErrNotSupported(funcName string, ver int) error {
return errors2.Wrap(ErrUnsupportedField, fmt.Sprintf("%s is not supported for %s", funcName, version.String(ver)))
}
// ThreadSafeEnumerator is a thread-safe counter of all objects created since the node's start.
type ThreadSafeEnumerator struct {
counter uint64
}
// Inc increments the enumerator and returns the new object count.
func (c *ThreadSafeEnumerator) Inc() uint64 {
return atomic.AddUint64(&c.counter, 1)
}

View File

@@ -5,10 +5,6 @@ go_library(
srcs = ["multi_value_slice.go"],
importpath = "github.com/prysmaticlabs/prysm/v4/container/multi-value-slice",
visibility = ["//visibility:public"],
deps = [
"//container/multi-value-slice/interfaces:go_default_library",
"@com_github_google_uuid//:go_default_library",
],
)
go_test(
@@ -18,6 +14,5 @@ go_test(
deps = [
"//testing/assert:go_default_library",
"//testing/require:go_default_library",
"@com_github_google_uuid//:go_default_library",
],
)

View File

@@ -1,9 +0,0 @@
load("@prysm//tools/go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["interfaces.go"],
importpath = "github.com/prysmaticlabs/prysm/v4/container/multi-value-slice/interfaces",
visibility = ["//visibility:public"],
deps = ["@com_github_google_uuid//:go_default_library"],
)

View File

@@ -1,9 +0,0 @@
package interfaces
import "github.com/google/uuid"
// Identifiable represents an object that can be uniquely identified by its Id.
type Identifiable interface {
Id() uuid.UUID
SetId(id uuid.UUID)
}

View File

@@ -92,20 +92,25 @@ package mvslice
import (
"fmt"
"sync"
"github.com/google/uuid"
"github.com/prysmaticlabs/prysm/v4/container/multi-value-slice/interfaces"
)
// Id is an object identifier.
type Id = uint64
// Identifiable represents an object that can be uniquely identified by its Id.
type Identifiable interface {
Id() Id
}
// MultiValueSlice defines an abstraction over all concrete implementations of the generic Slice.
type MultiValueSlice[O interfaces.Identifiable] interface {
Len(obj O) uuid.UUID
type MultiValueSlice[O Identifiable] interface {
Len(obj O) int
}
// Value defines a single value along with one or more IDs that share this value.
type Value[V any] struct {
val V
ids []uuid.UUID
ids []uint64
}
// MultiValueItem defines a collection of Value items.
@@ -119,11 +124,11 @@ type MultiValueItem[V any] struct {
// - O interfaces.Identifiable - the type of objects sharing the slice. The constraint is required
// because we need a way to compare objects against each other in order to know which objects
// values should be accessed.
type Slice[V comparable, O interfaces.Identifiable] struct {
type Slice[V comparable, O Identifiable] struct {
sharedItems []V
individualItems map[uint64]*MultiValueItem[V]
appendedItems []*MultiValueItem[V]
cachedLengths map[uuid.UUID]int
cachedLengths map[uint64]int
lock sync.RWMutex
}
@@ -132,7 +137,7 @@ func (s *Slice[V, O]) Init(items []V) {
s.sharedItems = items
s.individualItems = map[uint64]*MultiValueItem[V]{}
s.appendedItems = []*MultiValueItem[V]{}
s.cachedLengths = map[uuid.UUID]int{}
s.cachedLengths = map[uint64]int{}
}
// Len returns the number of items for the input object.
@@ -283,7 +288,7 @@ func (s *Slice[V, O]) Append(obj O, val V) {
defer s.lock.Unlock()
if len(s.appendedItems) == 0 {
s.appendedItems = append(s.appendedItems, &MultiValueItem[V]{Values: []*Value[V]{{val: val, ids: []uuid.UUID{obj.Id()}}}})
s.appendedItems = append(s.appendedItems, &MultiValueItem[V]{Values: []*Value[V]{{val: val, ids: []uint64{obj.Id()}}}})
s.cachedLengths[obj.Id()] = len(s.sharedItems) + 1
return
}
@@ -306,7 +311,7 @@ func (s *Slice[V, O]) Append(obj O, val V) {
}
}
if newValue {
item.Values = append(item.Values, &Value[V]{val: val, ids: []uuid.UUID{obj.Id()}})
item.Values = append(item.Values, &Value[V]{val: val, ids: []uint64{obj.Id()}})
}
l, ok := s.cachedLengths[obj.Id()]
@@ -320,7 +325,7 @@ func (s *Slice[V, O]) Append(obj O, val V) {
}
}
s.appendedItems = append(s.appendedItems, &MultiValueItem[V]{Values: []*Value[V]{{val: val, ids: []uuid.UUID{obj.Id()}}}})
s.appendedItems = append(s.appendedItems, &MultiValueItem[V]{Values: []*Value[V]{{val: val, ids: []uint64{obj.Id()}}}})
s.cachedLengths[obj.Id()] = s.cachedLengths[obj.Id()] + 1
}
@@ -419,7 +424,7 @@ func (s *Slice[V, O]) updateOriginalItem(obj O, index uint64, val V) {
}
if !ok {
s.individualItems[index] = &MultiValueItem[V]{Values: []*Value[V]{{val: val, ids: []uuid.UUID{obj.Id()}}}}
s.individualItems[index] = &MultiValueItem[V]{Values: []*Value[V]{{val: val, ids: []uint64{obj.Id()}}}}
} else {
newValue := true
for _, v := range ind.Values {
@@ -430,7 +435,7 @@ func (s *Slice[V, O]) updateOriginalItem(obj O, index uint64, val V) {
}
}
if newValue {
ind.Values = append(ind.Values, &Value[V]{val: val, ids: []uuid.UUID{obj.Id()}})
ind.Values = append(ind.Values, &Value[V]{val: val, ids: []uint64{obj.Id()}})
}
}
}
@@ -464,13 +469,13 @@ func (s *Slice[V, O]) updateAppendedItem(obj O, index uint64, val V) error {
}
}
if newValue {
item.Values = append(item.Values, &Value[V]{val: val, ids: []uuid.UUID{obj.Id()}})
item.Values = append(item.Values, &Value[V]{val: val, ids: []uint64{obj.Id()}})
}
return nil
}
func containsId(ids []uuid.UUID, wanted uuid.UUID) (int, bool) {
func containsId(ids []uint64, wanted uint64) (int, bool) {
for i, id := range ids {
if id == wanted {
return i, true

View File

@@ -4,40 +4,31 @@ import (
"math/rand"
"testing"
"github.com/google/uuid"
"github.com/prysmaticlabs/prysm/v4/testing/assert"
"github.com/prysmaticlabs/prysm/v4/testing/require"
)
var (
id1 = uuid.New()
id2 = uuid.New()
id999 = uuid.New()
)
type testObject struct {
id uuid.UUID
slice *Slice[int, *testObject]
id uint64
}
func (o *testObject) Id() uuid.UUID {
func (o *testObject) Id() uint64 {
return o.id
}
func (o *testObject) SetId(id uuid.UUID) {
func (o *testObject) SetId(id uint64) {
o.id = id
}
func TestLen(t *testing.T) {
s := &Slice[int, *testObject]{}
s.Init([]int{1, 2, 3})
id := uuid.New()
s.cachedLengths[id] = 123
s.cachedLengths[1] = 123
t.Run("cached", func(t *testing.T) {
assert.Equal(t, 123, s.Len(&testObject{id: id}))
assert.Equal(t, 123, s.Len(&testObject{id: 1}))
})
t.Run("not cached", func(t *testing.T) {
assert.Equal(t, 3, s.Len(&testObject{id: uuid.New()}))
assert.Equal(t, 3, s.Len(&testObject{id: 999}))
})
}
@@ -51,12 +42,12 @@ func TestCopy(t *testing.T) {
// - length of destination object is cached
s := setup()
src := &testObject{id: id1, slice: s}
dst := &testObject{id: id999, slice: s}
src := &testObject{id: 1}
dst := &testObject{id: 999}
s.Copy(src, dst)
assert.Equal(t, (*MultiValueItem[int])(nil), dst.slice.individualItems[0])
assert.Equal(t, (*MultiValueItem[int])(nil), s.individualItems[0])
assertIndividualFound(t, s, dst.id, 1, 1)
assertIndividualFound(t, s, dst.id, 2, 3)
assertIndividualFound(t, s, dst.id, 3, 1)
@@ -64,7 +55,7 @@ func TestCopy(t *testing.T) {
assertAppendedFound(t, s, dst.id, 0, 1)
assertAppendedFound(t, s, dst.id, 1, 3)
assertAppendedNotFound(t, s, dst.id, 2)
l, ok := s.cachedLengths[id999]
l, ok := s.cachedLengths[999]
require.Equal(t, true, ok)
assert.Equal(t, 7, l)
}
@@ -76,8 +67,8 @@ func TestValue(t *testing.T) {
// - correct values are returned for an object without appended items
s := setup()
first := &testObject{id: id1, slice: s}
second := &testObject{id: id2, slice: s}
first := &testObject{id: 1}
second := &testObject{id: 2}
v := s.Value(first)
@@ -104,9 +95,8 @@ func TestValue(t *testing.T) {
s = &Slice[int, *testObject]{}
s.Init([]int{1, 2, 3})
id := uuid.New()
v = s.Value(&testObject{id: id})
v = s.Value(&testObject{id: 999})
require.Equal(t, 3, len(v))
assert.Equal(t, 1, v[0])
@@ -122,8 +112,8 @@ func TestAt(t *testing.T) {
// - ERROR when index not too large in general, but too large for an object
s := setup()
first := &testObject{id: id1, slice: s}
second := &testObject{id: id2, slice: s}
first := &testObject{id: 1}
second := &testObject{id: 2}
v, err := s.At(first, 0)
require.NoError(t, err)
@@ -194,8 +184,8 @@ func TestUpdateAt(t *testing.T) {
// - ERROR when index not too large in general, but too large for an object
s := setup()
first := &testObject{id: id1, slice: s}
second := &testObject{id: id2, slice: s}
first := &testObject{id: 1}
second := &testObject{id: 2}
require.NoError(t, s.UpdateAt(first, 0, 999))
assert.Equal(t, 123, s.sharedItems[0])
@@ -258,8 +248,8 @@ func TestAppend(t *testing.T) {
// we want to start with the simplest slice possible
s := &Slice[int, *testObject]{}
s.Init([]int{0})
first := &testObject{id: id1, slice: s}
second := &testObject{id: id2, slice: s}
first := &testObject{id: 1}
second := &testObject{id: 2}
// append first value ever
s.Append(first, 1)
@@ -306,7 +296,7 @@ func TestDetach(t *testing.T) {
// - length removed from cache
s := setup()
obj := &testObject{id: id1, slice: s}
obj := &testObject{id: 1}
s.Detach(obj)
@@ -352,11 +342,11 @@ func setup() *Slice[int, *testObject] {
Values: []*Value[int]{
{
val: 1,
ids: []uuid.UUID{id1},
ids: []uint64{1},
},
{
val: 2,
ids: []uuid.UUID{id2},
ids: []uint64{2},
},
},
}
@@ -364,7 +354,7 @@ func setup() *Slice[int, *testObject] {
Values: []*Value[int]{
{
val: 3,
ids: []uuid.UUID{id1, id2},
ids: []uint64{1, 2},
},
},
}
@@ -372,7 +362,7 @@ func setup() *Slice[int, *testObject] {
Values: []*Value[int]{
{
val: 1,
ids: []uuid.UUID{id1},
ids: []uint64{1},
},
},
}
@@ -380,7 +370,7 @@ func setup() *Slice[int, *testObject] {
Values: []*Value[int]{
{
val: 2,
ids: []uuid.UUID{id2},
ids: []uint64{2},
},
},
}
@@ -389,11 +379,11 @@ func setup() *Slice[int, *testObject] {
Values: []*Value[int]{
{
val: 1,
ids: []uuid.UUID{id1},
ids: []uint64{1},
},
{
val: 2,
ids: []uuid.UUID{id2},
ids: []uint64{2},
},
},
},
@@ -401,7 +391,7 @@ func setup() *Slice[int, *testObject] {
Values: []*Value[int]{
{
val: 3,
ids: []uuid.UUID{id1, id2},
ids: []uint64{1, 2},
},
},
},
@@ -409,18 +399,18 @@ func setup() *Slice[int, *testObject] {
Values: []*Value[int]{
{
val: 2,
ids: []uuid.UUID{id2},
ids: []uint64{2},
},
},
},
}
s.cachedLengths[id1] = 7
s.cachedLengths[id2] = 8
s.cachedLengths[1] = 7
s.cachedLengths[2] = 8
return s
}
func assertIndividualFound(t *testing.T, slice *Slice[int, *testObject], id uuid.UUID, itemIndex uint64, expected int) {
func assertIndividualFound(t *testing.T, slice *Slice[int, *testObject], id uint64, itemIndex uint64, expected int) {
found := false
for _, v := range slice.individualItems[itemIndex].Values {
for _, o := range v.ids {
@@ -433,7 +423,7 @@ func assertIndividualFound(t *testing.T, slice *Slice[int, *testObject], id uuid
assert.Equal(t, true, found)
}
func assertIndividualNotFound(t *testing.T, slice *Slice[int, *testObject], id uuid.UUID, itemIndex uint64) {
func assertIndividualNotFound(t *testing.T, slice *Slice[int, *testObject], id uint64, itemIndex uint64) {
found := false
for _, v := range slice.individualItems[itemIndex].Values {
for _, o := range v.ids {
@@ -445,7 +435,7 @@ func assertIndividualNotFound(t *testing.T, slice *Slice[int, *testObject], id u
assert.Equal(t, false, found)
}
func assertAppendedFound(t *testing.T, slice *Slice[int, *testObject], id uuid.UUID, itemIndex uint64, expected int) {
func assertAppendedFound(t *testing.T, slice *Slice[int, *testObject], id uint64, itemIndex uint64, expected int) {
found := false
for _, v := range slice.appendedItems[itemIndex].Values {
for _, o := range v.ids {
@@ -458,7 +448,7 @@ func assertAppendedFound(t *testing.T, slice *Slice[int, *testObject], id uuid.U
assert.Equal(t, true, found)
}
func assertAppendedNotFound(t *testing.T, slice *Slice[int, *testObject], id uuid.UUID, itemIndex uint64) {
func assertAppendedNotFound(t *testing.T, slice *Slice[int, *testObject], id uint64, itemIndex uint64) {
found := false
for _, v := range slice.appendedItems[itemIndex].Values {
for _, o := range v.ids {
@@ -485,12 +475,11 @@ func BenchmarkValue(b *testing.B) {
b.Run("100,000 equal individual items", func(b *testing.B) {
s := &Slice[int, *testObject]{}
s.Init(make([]int, _100k))
s.individualItems[0] = &MultiValueItem[int]{Values: []*Value[int]{{val: 999, ids: []uuid.UUID{}}}}
s.individualItems[0] = &MultiValueItem[int]{Values: []*Value[int]{{val: 999, ids: []uint64{}}}}
objs := make([]*testObject, _100k)
for i := 0; i < len(objs); i++ {
id := uuid.New()
objs[i] = &testObject{id: id, slice: s}
s.individualItems[0].Values[0].ids = append(s.individualItems[0].Values[0].ids, id)
objs[i] = &testObject{id: uint64(i)}
s.individualItems[0].Values[0].ids = append(s.individualItems[0].Values[0].ids, uint64(i))
}
for i := 0; i < b.N; i++ {
s.Value(objs[rand.Intn(_100k)])
@@ -501,9 +490,8 @@ func BenchmarkValue(b *testing.B) {
s.Init(make([]int, _100k))
objs := make([]*testObject, _100k)
for i := 0; i < len(objs); i++ {
id := uuid.New()
objs[i] = &testObject{id: id, slice: s}
s.individualItems[uint64(i)] = &MultiValueItem[int]{Values: []*Value[int]{{val: i, ids: []uuid.UUID{id}}}}
objs[i] = &testObject{id: uint64(i)}
s.individualItems[uint64(i)] = &MultiValueItem[int]{Values: []*Value[int]{{val: i, ids: []uint64{uint64(i)}}}}
}
for i := 0; i < b.N; i++ {
s.Value(objs[rand.Intn(_100k)])
@@ -512,12 +500,11 @@ func BenchmarkValue(b *testing.B) {
b.Run("100,000 shared items and 100,000 equal appended items", func(b *testing.B) {
s := &Slice[int, *testObject]{}
s.Init(make([]int, _100k))
s.appendedItems = []*MultiValueItem[int]{{Values: []*Value[int]{{val: 999, ids: []uuid.UUID{}}}}}
s.appendedItems = []*MultiValueItem[int]{{Values: []*Value[int]{{val: 999, ids: []uint64{}}}}}
objs := make([]*testObject, _100k)
for i := 0; i < len(objs); i++ {
id := uuid.New()
objs[i] = &testObject{id: id, slice: s}
s.appendedItems[0].Values[0].ids = append(s.appendedItems[0].Values[0].ids, id)
objs[i] = &testObject{id: uint64(i)}
s.appendedItems[0].Values[0].ids = append(s.appendedItems[0].Values[0].ids, uint64(i))
}
for i := 0; i < b.N; i++ {
s.Value(objs[rand.Intn(_100k)])
@@ -529,9 +516,8 @@ func BenchmarkValue(b *testing.B) {
s.appendedItems = []*MultiValueItem[int]{}
objs := make([]*testObject, _100k)
for i := 0; i < len(objs); i++ {
id := uuid.New()
objs[i] = &testObject{id: id, slice: s}
s.appendedItems = append(s.appendedItems, &MultiValueItem[int]{Values: []*Value[int]{{val: i, ids: []uuid.UUID{id}}}})
objs[i] = &testObject{id: uint64(i)}
s.appendedItems = append(s.appendedItems, &MultiValueItem[int]{Values: []*Value[int]{{val: i, ids: []uint64{uint64(i)}}}})
}
for i := 0; i < b.N; i++ {
s.Value(objs[rand.Intn(_100k)])
@@ -547,12 +533,11 @@ func BenchmarkValue(b *testing.B) {
b.Run("1,000,000 equal individual items", func(b *testing.B) {
s := &Slice[int, *testObject]{}
s.Init(make([]int, _1m))
s.individualItems[0] = &MultiValueItem[int]{Values: []*Value[int]{{val: 999, ids: []uuid.UUID{}}}}
s.individualItems[0] = &MultiValueItem[int]{Values: []*Value[int]{{val: 999, ids: []uint64{}}}}
objs := make([]*testObject, _1m)
for i := 0; i < len(objs); i++ {
id := uuid.New()
objs[i] = &testObject{id: id, slice: s}
s.individualItems[0].Values[0].ids = append(s.individualItems[0].Values[0].ids, id)
objs[i] = &testObject{id: uint64(i)}
s.individualItems[0].Values[0].ids = append(s.individualItems[0].Values[0].ids, uint64(i))
}
for i := 0; i < b.N; i++ {
s.Value(objs[rand.Intn(_1m)])
@@ -563,9 +548,8 @@ func BenchmarkValue(b *testing.B) {
s.Init(make([]int, _1m))
objs := make([]*testObject, _1m)
for i := 0; i < len(objs); i++ {
id := uuid.New()
objs[i] = &testObject{id: id, slice: s}
s.individualItems[uint64(i)] = &MultiValueItem[int]{Values: []*Value[int]{{val: i, ids: []uuid.UUID{id}}}}
objs[i] = &testObject{id: uint64(i)}
s.individualItems[uint64(i)] = &MultiValueItem[int]{Values: []*Value[int]{{val: i, ids: []uint64{uint64(i)}}}}
}
for i := 0; i < b.N; i++ {
s.Value(objs[rand.Intn(_1m)])
@@ -574,12 +558,11 @@ func BenchmarkValue(b *testing.B) {
b.Run("1,000,000 shared items and 1,000,000 equal appended items", func(b *testing.B) {
s := &Slice[int, *testObject]{}
s.Init(make([]int, _1m))
s.appendedItems = []*MultiValueItem[int]{{Values: []*Value[int]{{val: 999, ids: []uuid.UUID{}}}}}
s.appendedItems = []*MultiValueItem[int]{{Values: []*Value[int]{{val: 999, ids: []uint64{}}}}}
objs := make([]*testObject, _1m)
for i := 0; i < len(objs); i++ {
id := uuid.New()
objs[i] = &testObject{id: id, slice: s}
s.appendedItems[0].Values[0].ids = append(s.appendedItems[0].Values[0].ids, id)
objs[i] = &testObject{id: uint64(i)}
s.appendedItems[0].Values[0].ids = append(s.appendedItems[0].Values[0].ids, uint64(i))
}
for i := 0; i < b.N; i++ {
s.Value(objs[rand.Intn(_1m)])
@@ -591,9 +574,8 @@ func BenchmarkValue(b *testing.B) {
s.appendedItems = []*MultiValueItem[int]{}
objs := make([]*testObject, _1m)
for i := 0; i < len(objs); i++ {
id := uuid.New()
objs[i] = &testObject{id: id, slice: s}
s.appendedItems = append(s.appendedItems, &MultiValueItem[int]{Values: []*Value[int]{{val: i, ids: []uuid.UUID{id}}}})
objs[i] = &testObject{id: uint64(i)}
s.appendedItems = append(s.appendedItems, &MultiValueItem[int]{Values: []*Value[int]{{val: i, ids: []uint64{uint64(i)}}}})
}
for i := 0; i < b.N; i++ {
s.Value(objs[rand.Intn(_1m)])
@@ -609,12 +591,11 @@ func BenchmarkValue(b *testing.B) {
b.Run("10,000,000 equal individual items", func(b *testing.B) {
s := &Slice[int, *testObject]{}
s.Init(make([]int, _10m))
s.individualItems[0] = &MultiValueItem[int]{Values: []*Value[int]{{val: 999, ids: []uuid.UUID{}}}}
s.individualItems[0] = &MultiValueItem[int]{Values: []*Value[int]{{val: 999, ids: []uint64{}}}}
objs := make([]*testObject, _10m)
for i := 0; i < len(objs); i++ {
id := uuid.New()
objs[i] = &testObject{id: id, slice: s}
s.individualItems[0].Values[0].ids = append(s.individualItems[0].Values[0].ids, id)
objs[i] = &testObject{id: uint64(i)}
s.individualItems[0].Values[0].ids = append(s.individualItems[0].Values[0].ids, uint64(i))
}
for i := 0; i < b.N; i++ {
s.Value(objs[rand.Intn(_10m)])
@@ -625,9 +606,8 @@ func BenchmarkValue(b *testing.B) {
s.Init(make([]int, _10m))
objs := make([]*testObject, _10m)
for i := 0; i < len(objs); i++ {
id := uuid.New()
objs[i] = &testObject{id: id, slice: s}
s.individualItems[uint64(i)] = &MultiValueItem[int]{Values: []*Value[int]{{val: i, ids: []uuid.UUID{id}}}}
objs[i] = &testObject{id: uint64(i)}
s.individualItems[uint64(i)] = &MultiValueItem[int]{Values: []*Value[int]{{val: i, ids: []uint64{uint64(i)}}}}
}
for i := 0; i < b.N; i++ {
s.Value(objs[rand.Intn(_10m)])
@@ -636,12 +616,11 @@ func BenchmarkValue(b *testing.B) {
b.Run("10,000,000 shared items and 10,000,000 equal appended items", func(b *testing.B) {
s := &Slice[int, *testObject]{}
s.Init(make([]int, _10m))
s.appendedItems = []*MultiValueItem[int]{{Values: []*Value[int]{{val: 999, ids: []uuid.UUID{}}}}}
s.appendedItems = []*MultiValueItem[int]{{Values: []*Value[int]{{val: 999, ids: []uint64{}}}}}
objs := make([]*testObject, _10m)
for i := 0; i < len(objs); i++ {
id := uuid.New()
objs[i] = &testObject{id: id, slice: s}
s.appendedItems[0].Values[0].ids = append(s.appendedItems[0].Values[0].ids, id)
objs[i] = &testObject{id: uint64(i)}
s.appendedItems[0].Values[0].ids = append(s.appendedItems[0].Values[0].ids, uint64(i))
}
for i := 0; i < b.N; i++ {
s.Value(objs[rand.Intn(_10m)])
@@ -653,9 +632,8 @@ func BenchmarkValue(b *testing.B) {
s.appendedItems = []*MultiValueItem[int]{}
objs := make([]*testObject, _10m)
for i := 0; i < len(objs); i++ {
id := uuid.New()
objs[i] = &testObject{id: id, slice: s}
s.appendedItems = append(s.appendedItems, &MultiValueItem[int]{Values: []*Value[int]{{val: i, ids: []uuid.UUID{id}}}})
objs[i] = &testObject{id: uint64(i)}
s.appendedItems = append(s.appendedItems, &MultiValueItem[int]{Values: []*Value[int]{{val: i, ids: []uint64{uint64(i)}}}})
}
for i := 0; i < b.N; i++ {
s.Value(objs[rand.Intn(_10m)])

View File

@@ -89,24 +89,65 @@ func (s *PremineGenesisConfig) prepare(ctx context.Context) (state.BeaconState,
func (s *PremineGenesisConfig) empty() (state.BeaconState, error) {
var e state.BeaconState
var err error
bRoots := make([][]byte, fieldparams.BlockRootsLength)
for i := range bRoots {
bRoots[i] = bytesutil.PadTo([]byte{}, 32)
}
sRoots := make([][]byte, fieldparams.StateRootsLength)
for i := range sRoots {
sRoots[i] = bytesutil.PadTo([]byte{}, 32)
}
mixes := make([][]byte, fieldparams.RandaoMixesLength)
for i := range mixes {
mixes[i] = bytesutil.PadTo([]byte{}, 32)
}
switch s.Version {
case version.Phase0:
e, err = state_native.InitializeFromProtoPhase0(&ethpb.BeaconState{})
e, err = state_native.InitializeFromProtoPhase0(&ethpb.BeaconState{
BlockRoots: bRoots,
StateRoots: sRoots,
RandaoMixes: mixes,
Balances: []uint64{},
Validators: []*ethpb.Validator{},
})
if err != nil {
return nil, err
}
case version.Altair:
e, err = state_native.InitializeFromProtoAltair(&ethpb.BeaconStateAltair{})
e, err = state_native.InitializeFromProtoAltair(&ethpb.BeaconStateAltair{
BlockRoots: bRoots,
StateRoots: sRoots,
RandaoMixes: mixes,
Balances: []uint64{},
InactivityScores: []uint64{},
Validators: []*ethpb.Validator{},
})
if err != nil {
return nil, err
}
case version.Bellatrix:
e, err = state_native.InitializeFromProtoBellatrix(&ethpb.BeaconStateBellatrix{})
e, err = state_native.InitializeFromProtoBellatrix(&ethpb.BeaconStateBellatrix{
BlockRoots: bRoots,
StateRoots: sRoots,
RandaoMixes: mixes,
Balances: []uint64{},
InactivityScores: []uint64{},
Validators: []*ethpb.Validator{},
})
if err != nil {
return nil, err
}
case version.Capella:
e, err = state_native.InitializeFromProtoCapella(&ethpb.BeaconStateCapella{})
e, err = state_native.InitializeFromProtoCapella(&ethpb.BeaconStateCapella{
BlockRoots: bRoots,
StateRoots: sRoots,
RandaoMixes: mixes,
Balances: []uint64{},
InactivityScores: []uint64{},
Validators: []*ethpb.Validator{},
})
if err != nil {
return nil, err
}
@@ -121,12 +162,6 @@ func (s *PremineGenesisConfig) empty() (state.BeaconState, error) {
if err = e.SetSlot(0); err != nil {
return nil, err
}
if err = e.SetValidators([]*ethpb.Validator{}); err != nil {
return nil, err
}
if err = e.SetBalances([]uint64{}); err != nil {
return nil, err
}
if err = e.SetJustificationBits([]byte{0}); err != nil {
return nil, err
}