implement slice for balances and inactivity scores

This commit is contained in:
rkapka
2023-05-05 14:04:09 +02:00
parent 2db4efa539
commit 59eb9df8d7
14 changed files with 223 additions and 179 deletions

View File

@@ -31,7 +31,7 @@ type BeaconState struct {
eth1DataVotes []*ethpb.Eth1Data
eth1DepositIndex uint64
validators []*ethpb.Validator
balances []uint64
balances *MultiValueBalances
randaoMixes *MultiValueRandaoMixes
slashings []uint64
previousEpochAttestations []*ethpb.PendingAttestation
@@ -42,7 +42,7 @@ type BeaconState struct {
previousJustifiedCheckpoint *ethpb.Checkpoint
currentJustifiedCheckpoint *ethpb.Checkpoint
finalizedCheckpoint *ethpb.Checkpoint
inactivityScores []uint64
inactivityScores *MultiValueInactivityScores
currentSyncCommittee *ethpb.SyncCommittee
nextSyncCommittee *ethpb.SyncCommittee
latestExecutionPayloadHeader *enginev1.ExecutionPayloadHeader

View File

@@ -31,7 +31,7 @@ type BeaconState struct {
eth1DataVotes []*ethpb.Eth1Data
eth1DepositIndex uint64
validators []*ethpb.Validator
balances []uint64
balances *MultiValueBalances
randaoMixes *MultiValueRandaoMixes
slashings []uint64
previousEpochAttestations []*ethpb.PendingAttestation
@@ -42,7 +42,7 @@ type BeaconState struct {
previousJustifiedCheckpoint *ethpb.Checkpoint
currentJustifiedCheckpoint *ethpb.Checkpoint
finalizedCheckpoint *ethpb.Checkpoint
inactivityScores []uint64
inactivityScores *MultiValueInactivityScores
currentSyncCommittee *ethpb.SyncCommittee
nextSyncCommittee *ethpb.SyncCommittee
latestExecutionPayloadHeader *enginev1.ExecutionPayloadHeader

View File

@@ -74,6 +74,12 @@ func NewFieldTrie(state *BeaconState, field types.FieldIndex, dataType types.Dat
numOfElems: l,
}, nil
case types.CompositeArray, types.CompressedArray:
var l int
if field == types.Balances {
l = elements.(multi_value_slice.MultiValueSlice).Len()
} else {
l = reflect.Indirect(reflect.ValueOf(elements)).Len()
}
return &FieldTrie{
fieldLayers: stateutil.ReturnTrieLayerVariable(fieldRoots, length),
field: field,
@@ -81,7 +87,7 @@ func NewFieldTrie(state *BeaconState, field types.FieldIndex, dataType types.Dat
reference: stateutil.NewRef(1),
RWMutex: new(sync.RWMutex),
length: length,
numOfElems: reflect.Indirect(reflect.ValueOf(elements)).Len(),
numOfElems: l,
}, nil
default:
return nil, errors.Errorf("unrecognized data type in field map: %v", reflect.TypeOf(dataType).Name())
@@ -113,13 +119,11 @@ func (f *FieldTrie) RecomputeTrie(state *BeaconState, indices []uint64, elements
if err != nil {
return [32]byte{}, err
}
var l int
if f.field == types.RandaoMixes || f.field == types.BlockRoots || f.field == types.StateRoots {
l = elements.(multi_value_slice.MultiValueSlice).Len()
f.numOfElems = elements.(multi_value_slice.MultiValueSlice).Len()
} else {
l = reflect.Indirect(reflect.ValueOf(elements)).Len()
f.numOfElems = reflect.Indirect(reflect.ValueOf(elements)).Len()
}
f.numOfElems = l
return fieldRoot, nil
case types.CompositeArray:
fieldRoot, f.fieldLayers, err = stateutil.RecomputeFromLayerVariable(fieldRoots, indices, f.fieldLayers)
@@ -155,7 +159,11 @@ func (f *FieldTrie) RecomputeTrie(state *BeaconState, indices []uint64, elements
if err != nil {
return [32]byte{}, err
}
f.numOfElems = reflect.Indirect(reflect.ValueOf(elements)).Len()
if f.field == types.Balances {
f.numOfElems = elements.(multi_value_slice.MultiValueSlice).Len()
} else {
f.numOfElems = reflect.Indirect(reflect.ValueOf(elements)).Len()
}
return stateutil.AddInMixin(fieldRoot, uint64(f.numOfElems))
default:
return [32]byte{}, errors.Errorf("unrecognized data type in field map: %v", reflect.TypeOf(f.dataType).Name())

View File

@@ -54,7 +54,7 @@ func validateElements(field types.FieldIndex, dataType types.DataType, elements
}
length *= comLength
}
if field == types.RandaoMixes || field == types.BlockRoots || field == types.StateRoots {
if field == types.RandaoMixes || field == types.BlockRoots || field == types.StateRoots || field == types.Balances || field == types.InactivityScores {
l := uint64(elements.(multi_value_slice.MultiValueSlice).Len())
if l > length {
return errors.Errorf("elements length is larger than expected for field %s: %d > %d", field.String(), l, length)
@@ -84,7 +84,7 @@ func fieldConverters(state *BeaconState, field types.FieldIndex, indices []uint6
case types.PreviousEpochAttestations, types.CurrentEpochAttestations:
return convertAttestations(indices, elements, convertAll)
case types.Balances:
return convertBalances(indices, elements, convertAll)
return convertBalances(state, indices, elements, convertAll)
default:
return [][32]byte{}, errors.Errorf("got unsupported type of %v", reflect.TypeOf(elements).Name())
}
@@ -147,12 +147,12 @@ func convertAttestations(indices []uint64, elements interface{}, convertAll bool
return handlePendingAttestationSlice(val, indices, convertAll)
}
func convertBalances(indices []uint64, elements interface{}, convertAll bool) ([][32]byte, error) {
val, ok := elements.([]uint64)
func convertBalances(state *BeaconState, indices []uint64, elements interface{}, convertAll bool) ([][32]byte, error) {
val, ok := elements.(*MultiValueBalances)
if !ok {
return nil, errors.Errorf("Wanted type of %T but got %T", []uint64{}, elements)
return nil, errors.Errorf("Wanted type of %T but got %T", &MultiValueBalances{}, elements)
}
return handleBalanceSlice(val, indices, convertAll)
return handleBalanceSlice(val.Value(state), indices, convertAll)
}
// handleByteArrays computes and returns byte arrays in a slice of root format.

View File

@@ -79,16 +79,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

@@ -34,7 +34,7 @@ func (b *BeaconState) ToProtoUnsafe() interface{} {
Eth1DataVotes: b.eth1DataVotes,
Eth1DepositIndex: b.eth1DepositIndex,
Validators: b.validators,
Balances: b.balances,
Balances: b.balances.Value(b),
RandaoMixes: rm.Slice(),
Slashings: b.slashings,
PreviousEpochAttestations: b.previousEpochAttestations,
@@ -58,7 +58,7 @@ func (b *BeaconState) ToProtoUnsafe() interface{} {
Eth1DataVotes: b.eth1DataVotes,
Eth1DepositIndex: b.eth1DepositIndex,
Validators: b.validators,
Balances: b.balances,
Balances: b.balances.Value(b),
RandaoMixes: rm.Slice(),
Slashings: b.slashings,
PreviousEpochParticipation: b.previousEpochParticipation,
@@ -67,7 +67,7 @@ func (b *BeaconState) ToProtoUnsafe() interface{} {
PreviousJustifiedCheckpoint: b.previousJustifiedCheckpoint,
CurrentJustifiedCheckpoint: b.currentJustifiedCheckpoint,
FinalizedCheckpoint: b.finalizedCheckpoint,
InactivityScores: b.inactivityScores,
InactivityScores: b.inactivityScores.Value(b),
CurrentSyncCommittee: b.currentSyncCommittee,
NextSyncCommittee: b.nextSyncCommittee,
}
@@ -85,7 +85,7 @@ func (b *BeaconState) ToProtoUnsafe() interface{} {
Eth1DataVotes: b.eth1DataVotes,
Eth1DepositIndex: b.eth1DepositIndex,
Validators: b.validators,
Balances: b.balances,
Balances: b.balances.Value(b),
RandaoMixes: rm.Slice(),
Slashings: b.slashings,
PreviousEpochParticipation: b.previousEpochParticipation,
@@ -94,7 +94,7 @@ func (b *BeaconState) ToProtoUnsafe() interface{} {
PreviousJustifiedCheckpoint: b.previousJustifiedCheckpoint,
CurrentJustifiedCheckpoint: b.currentJustifiedCheckpoint,
FinalizedCheckpoint: b.finalizedCheckpoint,
InactivityScores: b.inactivityScores,
InactivityScores: b.inactivityScores.Value(b),
CurrentSyncCommittee: b.currentSyncCommittee,
NextSyncCommittee: b.nextSyncCommittee,
LatestExecutionPayloadHeader: b.latestExecutionPayloadHeader,
@@ -113,7 +113,7 @@ func (b *BeaconState) ToProtoUnsafe() interface{} {
Eth1DataVotes: b.eth1DataVotes,
Eth1DepositIndex: b.eth1DepositIndex,
Validators: b.validators,
Balances: b.balances,
Balances: b.balances.Value(b),
RandaoMixes: rm.Slice(),
Slashings: b.slashings,
PreviousEpochParticipation: b.previousEpochParticipation,
@@ -122,7 +122,7 @@ func (b *BeaconState) ToProtoUnsafe() interface{} {
PreviousJustifiedCheckpoint: b.previousJustifiedCheckpoint,
CurrentJustifiedCheckpoint: b.currentJustifiedCheckpoint,
FinalizedCheckpoint: b.finalizedCheckpoint,
InactivityScores: b.inactivityScores,
InactivityScores: b.inactivityScores.Value(b),
CurrentSyncCommittee: b.currentSyncCommittee,
NextSyncCommittee: b.nextSyncCommittee,
LatestExecutionPayloadHeader: b.latestExecutionPayloadHeaderCapella,
@@ -145,9 +145,41 @@ func (b *BeaconState) ToProto() interface{} {
defer b.lock.RUnlock()
gvrCopy := b.genesisValidatorsRoot
br := customtypes.BlockRoots(b.blockRoots.Value(b))
brSlice := br.Slice()
// TODO: Should this be done in Slice()?
brCopy := make([][]byte, len(br))
for i, v := range brSlice {
copy(brCopy[i], v)
}
sr := customtypes.StateRoots(b.stateRoots.Value(b))
srSlice := sr.Slice()
// TODO: Should this be done in Slice()?
srCopy := make([][]byte, len(sr))
for i, v := range srSlice {
copy(srCopy[i], v)
}
rm := customtypes.RandaoMixes(b.randaoMixes.Value(b))
rmSlice := rm.Slice()
// TODO: Should this be done in Slice()?
rmCopy := make([][]byte, len(rm))
for i, v := range rmSlice {
copy(rmCopy[i], v)
}
balances := b.balances.Value(b)
balancesCopy := make([]uint64, len(balances))
copy(balancesCopy, balances)
var inactivityScoresCopy []uint64
if b.version > version.Phase0 {
inactivityScores := b.inactivityScores.Value(b)
inactivityScoresCopy = make([]uint64, len(inactivityScores))
copy(inactivityScoresCopy, inactivityScores)
}
switch b.version {
case version.Phase0:
@@ -157,15 +189,15 @@ func (b *BeaconState) ToProto() interface{} {
Slot: b.slot,
Fork: b.forkVal(),
LatestBlockHeader: b.latestBlockHeaderVal(),
BlockRoots: br.Slice(),
StateRoots: sr.Slice(),
BlockRoots: brCopy,
StateRoots: srCopy,
HistoricalRoots: b.historicalRoots.Slice(),
Eth1Data: b.eth1DataVal(),
Eth1DataVotes: b.eth1DataVotesVal(),
Eth1DepositIndex: b.eth1DepositIndex,
Validators: b.validatorsVal(),
Balances: b.balancesVal(),
RandaoMixes: rm.Slice(),
Balances: balancesCopy,
RandaoMixes: rmCopy,
Slashings: b.slashingsVal(),
PreviousEpochAttestations: b.previousEpochAttestationsVal(),
CurrentEpochAttestations: b.currentEpochAttestationsVal(),
@@ -181,15 +213,15 @@ func (b *BeaconState) ToProto() interface{} {
Slot: b.slot,
Fork: b.forkVal(),
LatestBlockHeader: b.latestBlockHeaderVal(),
BlockRoots: br.Slice(),
StateRoots: sr.Slice(),
BlockRoots: brCopy,
StateRoots: srCopy,
HistoricalRoots: b.historicalRoots.Slice(),
Eth1Data: b.eth1DataVal(),
Eth1DataVotes: b.eth1DataVotesVal(),
Eth1DepositIndex: b.eth1DepositIndex,
Validators: b.validatorsVal(),
Balances: b.balancesVal(),
RandaoMixes: rm.Slice(),
Balances: balancesCopy,
RandaoMixes: rmCopy,
Slashings: b.slashingsVal(),
PreviousEpochParticipation: b.previousEpochParticipationVal(),
CurrentEpochParticipation: b.currentEpochParticipationVal(),
@@ -197,7 +229,7 @@ func (b *BeaconState) ToProto() interface{} {
PreviousJustifiedCheckpoint: b.previousJustifiedCheckpointVal(),
CurrentJustifiedCheckpoint: b.currentJustifiedCheckpointVal(),
FinalizedCheckpoint: b.finalizedCheckpointVal(),
InactivityScores: b.inactivityScoresVal(),
InactivityScores: inactivityScoresCopy,
CurrentSyncCommittee: b.currentSyncCommitteeVal(),
NextSyncCommittee: b.nextSyncCommitteeVal(),
}
@@ -208,15 +240,15 @@ func (b *BeaconState) ToProto() interface{} {
Slot: b.slot,
Fork: b.forkVal(),
LatestBlockHeader: b.latestBlockHeaderVal(),
BlockRoots: br.Slice(),
StateRoots: sr.Slice(),
BlockRoots: brCopy,
StateRoots: srCopy,
HistoricalRoots: b.historicalRoots.Slice(),
Eth1Data: b.eth1DataVal(),
Eth1DataVotes: b.eth1DataVotesVal(),
Eth1DepositIndex: b.eth1DepositIndex,
Validators: b.validatorsVal(),
Balances: b.balancesVal(),
RandaoMixes: rm.Slice(),
Balances: balancesCopy,
RandaoMixes: rmCopy,
Slashings: b.slashingsVal(),
PreviousEpochParticipation: b.previousEpochParticipationVal(),
CurrentEpochParticipation: b.currentEpochParticipationVal(),
@@ -224,7 +256,7 @@ func (b *BeaconState) ToProto() interface{} {
PreviousJustifiedCheckpoint: b.previousJustifiedCheckpointVal(),
CurrentJustifiedCheckpoint: b.currentJustifiedCheckpointVal(),
FinalizedCheckpoint: b.finalizedCheckpointVal(),
InactivityScores: b.inactivityScoresVal(),
InactivityScores: inactivityScoresCopy,
CurrentSyncCommittee: b.currentSyncCommitteeVal(),
NextSyncCommittee: b.nextSyncCommitteeVal(),
LatestExecutionPayloadHeader: b.latestExecutionPayloadHeaderVal(),
@@ -236,15 +268,15 @@ func (b *BeaconState) ToProto() interface{} {
Slot: b.slot,
Fork: b.forkVal(),
LatestBlockHeader: b.latestBlockHeaderVal(),
BlockRoots: br.Slice(),
StateRoots: sr.Slice(),
BlockRoots: brCopy,
StateRoots: srCopy,
HistoricalRoots: b.historicalRoots.Slice(),
Eth1Data: b.eth1DataVal(),
Eth1DataVotes: b.eth1DataVotesVal(),
Eth1DepositIndex: b.eth1DepositIndex,
Validators: b.validatorsVal(),
Balances: b.balancesVal(),
RandaoMixes: rm.Slice(),
Balances: balancesCopy,
RandaoMixes: rmCopy,
Slashings: b.slashingsVal(),
PreviousEpochParticipation: b.previousEpochParticipationVal(),
CurrentEpochParticipation: b.currentEpochParticipationVal(),
@@ -252,7 +284,7 @@ func (b *BeaconState) ToProto() interface{} {
PreviousJustifiedCheckpoint: b.previousJustifiedCheckpointVal(),
CurrentJustifiedCheckpoint: b.currentJustifiedCheckpointVal(),
FinalizedCheckpoint: b.finalizedCheckpointVal(),
InactivityScores: b.inactivityScoresVal(),
InactivityScores: inactivityScoresCopy,
CurrentSyncCommittee: b.currentSyncCommitteeVal(),
NextSyncCommittee: b.nextSyncCommitteeVal(),
LatestExecutionPayloadHeader: b.latestExecutionPayloadHeaderCapellaVal(),

View File

@@ -185,19 +185,7 @@ func (b *BeaconState) Balances() []uint64 {
b.lock.RLock()
defer b.lock.RUnlock()
return b.balancesVal()
}
// balancesVal of validators participating in consensus on the beacon chain.
// This assumes that a lock is already held on BeaconState.
func (b *BeaconState) balancesVal() []uint64 {
if b.balances == nil {
return nil
}
res := make([]uint64, len(b.balances))
copy(res, b.balances)
return res
return b.balances.Value(b)
}
// BalanceAtIndex of validator with the provided index.
@@ -209,10 +197,7 @@ func (b *BeaconState) BalanceAtIndex(idx primitives.ValidatorIndex) (uint64, err
b.lock.RLock()
defer b.lock.RUnlock()
if uint64(len(b.balances)) <= uint64(idx) {
return 0, fmt.Errorf("index of %d does not exist", idx)
}
return b.balances[idx], nil
return b.balances.At(b, uint64(idx))
}
// BalancesLength returns the length of the balances slice.
@@ -224,7 +209,7 @@ func (b *BeaconState) BalancesLength() int {
b.lock.RLock()
defer b.lock.RUnlock()
return b.balancesLength()
return b.balances.Len()
}
// Slashings of validators on the beacon chain.
@@ -264,17 +249,5 @@ func (b *BeaconState) InactivityScores() ([]uint64, error) {
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 b.inactivityScores == nil {
return nil
}
res := make([]uint64, len(b.inactivityScores))
copy(res, b.inactivityScores)
return res
return b.inactivityScores.Value(b), nil
}

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"
@@ -57,7 +58,10 @@ func (b *BeaconState) ExpectedWithdrawals() ([]*enginev1.Withdrawal, error) {
bound := mathutil.Min(uint64(len(b.validators)), params.BeaconConfig().MaxValidatorsPerWithdrawalsSweep)
for i := uint64(0); i < bound; i++ {
val := b.validators[validatorIndex]
balance := b.balances[validatorIndex]
balance, err := b.balances.At(b, uint64(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,

View File

@@ -125,7 +125,7 @@ func ComputeFieldRootsWithHasher(ctx context.Context, state *BeaconState) ([][]b
fieldRoots[types.Validators.RealPosition()] = validatorsRoot[:]
// Balances slice root.
balancesRoot, err := stateutil.Uint64ListRootWithRegistryLimit(state.balances)
balancesRoot, err := stateutil.Uint64ListRootWithRegistryLimit(state.balances.Value(state))
if err != nil {
return nil, errors.Wrap(err, "could not compute validator balances merkleization")
}
@@ -209,7 +209,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.inactivityScores.Value(state))
if err != nil {
return nil, errors.Wrap(err, "could not compute inactivityScoreRoot")
}

View File

@@ -9,8 +9,8 @@ type MultiValueRandaoMixes = multi_value_slice.Slice[[32]byte, *BeaconState]
func NewMultiValueRandaoMixes(mixes [][]byte) *MultiValueRandaoMixes {
items := make([]*multi_value_slice.MultiValue[[32]byte], fieldparams.RandaoMixesLength)
for i, b := range mixes {
items[i] = &multi_value_slice.MultiValue[[32]byte]{Shared: *(*[32]byte)(b), Individual: nil}
for i, v := range mixes {
items[i] = &multi_value_slice.MultiValue[[32]byte]{Shared: *(*[32]byte)(v), Individual: nil}
}
return &MultiValueRandaoMixes{
Items: items,
@@ -21,8 +21,8 @@ type MultiValueBlockRoots = multi_value_slice.Slice[[32]byte, *BeaconState]
func NewMultiValueBlockRoots(roots [][]byte) *MultiValueBlockRoots {
items := make([]*multi_value_slice.MultiValue[[32]byte], fieldparams.BlockRootsLength)
for i, b := range roots {
items[i] = &multi_value_slice.MultiValue[[32]byte]{Shared: *(*[32]byte)(b), Individual: nil}
for i, v := range roots {
items[i] = &multi_value_slice.MultiValue[[32]byte]{Shared: *(*[32]byte)(v), Individual: nil}
}
return &MultiValueBlockRoots{
Items: items,
@@ -33,10 +33,34 @@ type MultiValueStateRoots = multi_value_slice.Slice[[32]byte, *BeaconState]
func NewMultiValueStateRoots(roots [][]byte) *MultiValueStateRoots {
items := make([]*multi_value_slice.MultiValue[[32]byte], fieldparams.StateRootsLength)
for i, b := range roots {
items[i] = &multi_value_slice.MultiValue[[32]byte]{Shared: *(*[32]byte)(b), Individual: nil}
for i, v := range roots {
items[i] = &multi_value_slice.MultiValue[[32]byte]{Shared: *(*[32]byte)(v), Individual: nil}
}
return &MultiValueStateRoots{
Items: items,
}
}
type MultiValueBalances = multi_value_slice.Slice[uint64, *BeaconState]
func NewMultiValueBalances(balances []uint64) *MultiValueBalances {
items := make([]*multi_value_slice.MultiValue[uint64], len(balances))
for i, v := range balances {
items[i] = &multi_value_slice.MultiValue[uint64]{Shared: v, Individual: nil}
}
return &MultiValueBalances{
Items: items,
}
}
type MultiValueInactivityScores = multi_value_slice.Slice[uint64, *BeaconState]
func NewMultiValueInactivityScores(scores []uint64) *MultiValueInactivityScores {
items := make([]*multi_value_slice.MultiValue[uint64], len(scores))
for i, v := range scores {
items[i] = &multi_value_slice.MultiValue[uint64]{Shared: v, Individual: nil}
}
return &MultiValueInactivityScores{
Items: items,
}
}

View File

@@ -88,10 +88,7 @@ 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)
b.balances = val
b.balances = NewMultiValueBalances(val)
b.markFieldAsDirty(types.Balances)
b.rebuildTrie[types.Balances] = true
return nil
@@ -100,21 +97,12 @@ 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)
}
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)
if err := b.balances.UpdateAt(b, uint64(idx), val); err != nil {
return errors.Wrap(err, "could not update balances")
}
bals[idx] = val
b.balances = bals
b.markFieldAsDirty(types.Balances)
b.addDirtyIndices(types.Balances, []uint64{uint64(idx)})
return nil
@@ -188,15 +176,14 @@ func (b *BeaconState) AppendBalance(bal uint64) error {
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 := b.balances.Value(b)
balsCopy := make([]uint64, len(bals)+1)
copy(balsCopy, bals)
balIdx := len(balsCopy) - 1
balsCopy[balIdx] = bal
b.balances.Detach(b)
b.balances = NewMultiValueBalances(balsCopy)
b.balances = append(bals, bal)
balIdx := len(b.balances) - 1
b.markFieldAsDirty(types.Balances)
b.addDirtyIndices(types.Balances, []uint64{uint64(balIdx)})
return nil
@@ -211,14 +198,13 @@ func (b *BeaconState) AppendInactivityScore(s uint64) error {
return errNotSupported("AppendInactivityScore", b.version)
}
scores := b.inactivityScores
if b.sharedFieldReferences[types.InactivityScores].Refs() > 1 {
scores = b.inactivityScoresVal()
b.sharedFieldReferences[types.InactivityScores].MinusRef()
b.sharedFieldReferences[types.InactivityScores] = stateutil.NewRef(1)
}
scores := b.inactivityScores.Value(b)
scoresCopy := make([]uint64, len(scores)+1)
copy(scoresCopy, scores)
scoresCopy[len(scoresCopy)-1] = s
b.inactivityScores.Detach(b)
b.balances = NewMultiValueInactivityScores(scoresCopy)
b.inactivityScores = append(scores, s)
b.markFieldAsDirty(types.InactivityScores)
return nil
}
@@ -233,10 +219,7 @@ func (b *BeaconState) SetInactivityScores(val []uint64) error {
return errNotSupported("SetInactivityScores", b.version)
}
b.sharedFieldReferences[types.InactivityScores].MinusRef()
b.sharedFieldReferences[types.InactivityScores] = stateutil.NewRef(1)
b.inactivityScores = val
b.inactivityScores = NewMultiValueInactivityScores(val)
b.markFieldAsDirty(types.InactivityScores)
return nil
}

View File

@@ -83,10 +83,10 @@ var capellaFields = append(
)
const (
phase0SharedFieldRefCount = 7
altairSharedFieldRefCount = 8
bellatrixSharedFieldRefCount = 9
capellaSharedFieldRefCount = 11
phase0SharedFieldRefCount = 6
altairSharedFieldRefCount = 6
bellatrixSharedFieldRefCount = 7
capellaSharedFieldRefCount = 8
)
// InitializeFromProtoPhase0 the beacon state from a protobuf representation.
@@ -137,7 +137,7 @@ func InitializeFromProtoUnsafePhase0(st *ethpb.BeaconState) (state.BeaconState,
eth1DataVotes: st.Eth1DataVotes,
eth1DepositIndex: st.Eth1DepositIndex,
validators: st.Validators,
balances: st.Balances,
balances: NewMultiValueBalances(st.Balances),
slashings: st.Slashings,
previousEpochAttestations: st.PreviousEpochAttestations,
currentEpochAttestations: st.CurrentEpochAttestations,
@@ -169,7 +169,6 @@ func InitializeFromProtoUnsafePhase0(st *ethpb.BeaconState) (state.BeaconState,
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.Slashings] = stateutil.NewRef(1)
b.sharedFieldReferences[types.PreviousEpochAttestations] = stateutil.NewRef(1)
b.sharedFieldReferences[types.CurrentEpochAttestations] = stateutil.NewRef(1)
@@ -208,7 +207,7 @@ func InitializeFromProtoUnsafeAltair(st *ethpb.BeaconStateAltair) (state.BeaconS
eth1DataVotes: st.Eth1DataVotes,
eth1DepositIndex: st.Eth1DepositIndex,
validators: st.Validators,
balances: st.Balances,
balances: NewMultiValueBalances(st.Balances),
slashings: st.Slashings,
previousEpochParticipation: st.PreviousEpochParticipation,
currentEpochParticipation: st.CurrentEpochParticipation,
@@ -216,7 +215,7 @@ func InitializeFromProtoUnsafeAltair(st *ethpb.BeaconStateAltair) (state.BeaconS
previousJustifiedCheckpoint: st.PreviousJustifiedCheckpoint,
currentJustifiedCheckpoint: st.CurrentJustifiedCheckpoint,
finalizedCheckpoint: st.FinalizedCheckpoint,
inactivityScores: st.InactivityScores,
inactivityScores: NewMultiValueInactivityScores(st.InactivityScores),
currentSyncCommittee: st.CurrentSyncCommittee,
nextSyncCommittee: st.NextSyncCommittee,
@@ -243,11 +242,9 @@ func InitializeFromProtoUnsafeAltair(st *ethpb.BeaconStateAltair) (state.BeaconS
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.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.
state.StateCount.Inc()
// Finalizer runs when dst is being destroyed in garbage collection.
@@ -283,7 +280,7 @@ func InitializeFromProtoUnsafeBellatrix(st *ethpb.BeaconStateBellatrix) (state.B
eth1DataVotes: st.Eth1DataVotes,
eth1DepositIndex: st.Eth1DepositIndex,
validators: st.Validators,
balances: st.Balances,
balances: NewMultiValueBalances(st.Balances),
slashings: st.Slashings,
previousEpochParticipation: st.PreviousEpochParticipation,
currentEpochParticipation: st.CurrentEpochParticipation,
@@ -291,7 +288,7 @@ func InitializeFromProtoUnsafeBellatrix(st *ethpb.BeaconStateBellatrix) (state.B
previousJustifiedCheckpoint: st.PreviousJustifiedCheckpoint,
currentJustifiedCheckpoint: st.CurrentJustifiedCheckpoint,
finalizedCheckpoint: st.FinalizedCheckpoint,
inactivityScores: st.InactivityScores,
inactivityScores: NewMultiValueInactivityScores(st.InactivityScores),
currentSyncCommittee: st.CurrentSyncCommittee,
nextSyncCommittee: st.NextSyncCommittee,
latestExecutionPayloadHeader: st.LatestExecutionPayloadHeader,
@@ -319,11 +316,9 @@ func InitializeFromProtoUnsafeBellatrix(st *ethpb.BeaconStateBellatrix) (state.B
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.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.
state.StateCount.Inc()
@@ -360,7 +355,7 @@ func InitializeFromProtoUnsafeCapella(st *ethpb.BeaconStateCapella) (state.Beaco
eth1DataVotes: st.Eth1DataVotes,
eth1DepositIndex: st.Eth1DepositIndex,
validators: st.Validators,
balances: st.Balances,
balances: NewMultiValueBalances(st.Balances),
slashings: st.Slashings,
previousEpochParticipation: st.PreviousEpochParticipation,
currentEpochParticipation: st.CurrentEpochParticipation,
@@ -368,7 +363,7 @@ func InitializeFromProtoUnsafeCapella(st *ethpb.BeaconStateCapella) (state.Beaco
previousJustifiedCheckpoint: st.PreviousJustifiedCheckpoint,
currentJustifiedCheckpoint: st.CurrentJustifiedCheckpoint,
finalizedCheckpoint: st.FinalizedCheckpoint,
inactivityScores: st.InactivityScores,
inactivityScores: NewMultiValueInactivityScores(st.InactivityScores),
currentSyncCommittee: st.CurrentSyncCommittee,
nextSyncCommittee: st.NextSyncCommittee,
latestExecutionPayloadHeaderCapella: st.LatestExecutionPayloadHeader,
@@ -399,11 +394,9 @@ func InitializeFromProtoUnsafeCapella(st *ethpb.BeaconStateCapella) (state.Beaco
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.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.
@@ -484,6 +477,8 @@ func (b *BeaconState) Copy() state.BeaconState {
b.blockRoots.Copy(b, dst)
b.stateRoots.Copy(b, dst)
b.randaoMixes.Copy(b, dst)
b.balances.Copy(b, dst)
b.inactivityScores.Copy(b, dst)
switch b.version {
case version.Phase0:
@@ -764,7 +759,7 @@ 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)
return stateutil.Uint64ListRootWithRegistryLimit(b.inactivityScores.Value(b))
case types.CurrentSyncCommittee:
return stateutil.SyncCommitteeRoot(b.currentSyncCommittee)
case types.NextSyncCommittee:
@@ -859,9 +854,21 @@ func finalizerCleanup(b *BeaconState) {
delete(b.stateFieldLeaves, i)
}
b.blockRoots.Detach(b)
b.stateRoots.Detach(b)
b.randaoMixes.Detach(b)
if b.blockRoots != nil {
b.blockRoots.Detach(b)
}
if b.stateRoots != nil {
b.stateRoots.Detach(b)
}
if b.randaoMixes != nil {
b.randaoMixes.Detach(b)
}
if b.balances != nil {
b.balances.Detach(b)
}
if b.inactivityScores != nil {
b.inactivityScores.Detach(b)
}
state.StateCount.Sub(1)
}

View File

@@ -25,18 +25,18 @@ type Slice[V comparable, O any] struct {
lock sync.RWMutex
}
func (r *Slice[V, O]) Len() int {
return len(r.Items)
func (s *Slice[V, O]) Len() int {
return len(s.Items)
}
func (r *Slice[V, O]) Copy(src O, dst O) {
r.lock.Lock()
defer r.lock.Unlock()
func (s *Slice[V, O]) Copy(src O, dst O) {
s.lock.Lock()
defer s.lock.Unlock()
pSrc := reflect.ValueOf(src).Elem().Addr().Pointer()
pDst := reflect.ValueOf(dst).Elem().Addr().Pointer()
for _, item := range r.Items {
for _, item := range s.Items {
if item.Individual != nil {
outerLoop:
for _, mv := range item.Individual {
@@ -51,16 +51,16 @@ func (r *Slice[V, O]) Copy(src O, dst O) {
}
}
func (r *Slice[V, O]) Value(obj O) []V {
r.lock.RLock()
defer r.lock.RUnlock()
func (s *Slice[V, O]) Value(obj O) []V {
s.lock.RLock()
defer s.lock.RUnlock()
p := reflect.ValueOf(obj).Elem().Addr().Pointer()
v := make([]V, len(r.Items))
for i, item := range r.Items {
v := make([]V, len(s.Items))
for i, item := range s.Items {
if item.Individual == nil {
v[i] = r.Items[i].Shared
v[i] = s.Items[i].Shared
} else {
found := false
outerLoop:
@@ -74,7 +74,7 @@ func (r *Slice[V, O]) Value(obj O) []V {
}
}
if !found {
v[i] = r.Items[i].Shared
v[i] = s.Items[i].Shared
}
}
}
@@ -82,18 +82,18 @@ func (r *Slice[V, O]) Value(obj O) []V {
return v
}
func (r *Slice[V, O]) At(obj O, i uint64) (V, error) {
r.lock.RLock()
defer r.lock.RUnlock()
func (s *Slice[V, O]) At(obj O, i uint64) (V, error) {
s.lock.RLock()
defer s.lock.RUnlock()
if i >= uint64(len(r.Items)) {
if i >= uint64(len(s.Items)) {
var def V
return def, fmt.Errorf("index %d is out of bounds", i)
}
p := reflect.ValueOf(obj).Elem().Addr().Pointer()
item := r.Items[i]
item := s.Items[i]
if item.Individual == nil {
return item.Shared, nil
}
@@ -107,15 +107,15 @@ func (r *Slice[V, O]) At(obj O, i uint64) (V, error) {
return item.Shared, nil
}
func (r *Slice[V, O]) UpdateAt(obj O, i uint64, val V) error {
r.lock.Lock()
defer r.lock.Unlock()
func (s *Slice[V, O]) UpdateAt(obj O, i uint64, val V) error {
s.lock.Lock()
defer s.lock.Unlock()
if i >= uint64(len(r.Items)) {
if i >= uint64(len(s.Items)) {
return fmt.Errorf("index %d is out of bounds", i)
}
item := r.Items[i]
item := s.Items[i]
p := reflect.ValueOf(obj).Elem().Addr().Pointer()
@@ -152,13 +152,13 @@ outerLoop:
return nil
}
func (r *Slice[V, O]) Detach(obj O) {
r.lock.Lock()
defer r.lock.Unlock()
func (s *Slice[V, O]) Detach(obj O) {
s.lock.Lock()
defer s.lock.Unlock()
p := reflect.ValueOf(obj).Elem().Addr().Pointer()
for _, item := range r.Items {
for _, item := range s.Items {
outerLoop:
for mvi, mv := range item.Individual {
for oi, o := range mv.objs {

View File

@@ -105,22 +105,45 @@ func (s *PremineGenesisConfig) empty() (state.BeaconState, error) {
switch s.Version {
case version.Phase0:
e, err = state_native.InitializeFromProtoPhase0(&ethpb.BeaconState{BlockRoots: bRoots, StateRoots: sRoots, RandaoMixes: mixes})
e, err = state_native.InitializeFromProtoPhase0(&ethpb.BeaconState{
BlockRoots: bRoots,
StateRoots: sRoots,
RandaoMixes: mixes,
Balances: []uint64{},
})
if err != nil {
return nil, err
}
case version.Altair:
e, err = state_native.InitializeFromProtoAltair(&ethpb.BeaconStateAltair{BlockRoots: bRoots, StateRoots: sRoots, RandaoMixes: mixes})
e, err = state_native.InitializeFromProtoAltair(&ethpb.BeaconStateAltair{
BlockRoots: bRoots,
StateRoots: sRoots,
RandaoMixes: mixes,
Balances: []uint64{},
InactivityScores: []uint64{},
})
if err != nil {
return nil, err
}
case version.Bellatrix:
e, err = state_native.InitializeFromProtoBellatrix(&ethpb.BeaconStateBellatrix{BlockRoots: bRoots, StateRoots: sRoots, RandaoMixes: mixes})
e, err = state_native.InitializeFromProtoBellatrix(&ethpb.BeaconStateBellatrix{
BlockRoots: bRoots,
StateRoots: sRoots,
RandaoMixes: mixes,
Balances: []uint64{},
InactivityScores: []uint64{},
})
if err != nil {
return nil, err
}
case version.Capella:
e, err = state_native.InitializeFromProtoCapella(&ethpb.BeaconStateCapella{BlockRoots: bRoots, StateRoots: sRoots, RandaoMixes: mixes})
e, err = state_native.InitializeFromProtoCapella(&ethpb.BeaconStateCapella{
BlockRoots: bRoots,
StateRoots: sRoots,
RandaoMixes: mixes,
Balances: []uint64{},
InactivityScores: []uint64{},
})
if err != nil {
return nil, err
}