package v2 import ( "fmt" "github.com/pkg/errors" types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/beacon-chain/state" v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/shared/bytesutil" ) // ValidatorIndexOutOfRangeError represents an error scenario where a validator does not exist // at a given index in the validator's array. type ValidatorIndexOutOfRangeError struct { message string } var ( // ErrNilValidatorsInState returns when accessing validators in the state while the state has a // nil slice for the validators field. ErrNilValidatorsInState = errors.New("state has nil validator slice") ) // NewValidatorIndexOutOfRangeError creates a new error instance. func NewValidatorIndexOutOfRangeError(index types.ValidatorIndex) ValidatorIndexOutOfRangeError { return ValidatorIndexOutOfRangeError{ message: fmt.Sprintf("index %d out of range", index), } } // Error returns the underlying error message. func (e *ValidatorIndexOutOfRangeError) Error() string { return e.message } // Validators participating in consensus on the beacon chain. func (b *BeaconState) Validators() []*ethpb.Validator { if !b.hasInnerState() { return nil } if b.state.Validators == nil { return nil } b.lock.RLock() defer b.lock.RUnlock() return b.validators() } // validators participating in consensus on the beacon chain. // This assumes that a lock is already held on BeaconState. func (b *BeaconState) validators() []*ethpb.Validator { if !b.hasInnerState() { return nil } if b.state.Validators == nil { return nil } res := make([]*ethpb.Validator, len(b.state.Validators)) for i := 0; i < len(res); i++ { val := b.state.Validators[i] if val == nil { continue } res[i] = ethpb.CopyValidator(val) } return res } // references of validators participating in consensus on the beacon chain. // This assumes that a lock is already held on BeaconState. This does not // copy fully and instead just copies the reference. func (b *BeaconState) validatorsReferences() []*ethpb.Validator { if !b.hasInnerState() { return nil } if b.state.Validators == nil { return nil } res := make([]*ethpb.Validator, len(b.state.Validators)) for i := 0; i < len(res); i++ { validator := b.state.Validators[i] if validator == nil { continue } // copy validator reference instead. res[i] = validator } return res } // ValidatorAtIndex is the validator at the provided index. func (b *BeaconState) ValidatorAtIndex(idx types.ValidatorIndex) (*ethpb.Validator, error) { if !b.hasInnerState() { return nil, ErrNilInnerState } if b.state.Validators == nil { return ðpb.Validator{}, nil } if uint64(len(b.state.Validators)) <= uint64(idx) { e := NewValidatorIndexOutOfRangeError(idx) return nil, &e } b.lock.RLock() defer b.lock.RUnlock() val := b.state.Validators[idx] return ethpb.CopyValidator(val), nil } // ValidatorAtIndexReadOnly is the validator at the provided index. This method // doesn't clone the validator. func (b *BeaconState) ValidatorAtIndexReadOnly(idx types.ValidatorIndex) (state.ReadOnlyValidator, error) { if !b.hasInnerState() { return nil, ErrNilInnerState } if b.state.Validators == nil { return nil, ErrNilValidatorsInState } if uint64(len(b.state.Validators)) <= uint64(idx) { e := NewValidatorIndexOutOfRangeError(idx) return nil, &e } b.lock.RLock() defer b.lock.RUnlock() return v1.NewValidator(b.state.Validators[idx]) } // ValidatorIndexByPubkey returns a given validator by its 48-byte public key. func (b *BeaconState) ValidatorIndexByPubkey(key [48]byte) (types.ValidatorIndex, bool) { if b == nil || b.valMapHandler == nil || b.valMapHandler.IsNil() { return 0, false } b.lock.RLock() defer b.lock.RUnlock() numOfVals := len(b.state.Validators) idx, ok := b.valMapHandler.Get(key) if ok && numOfVals <= int(idx) { return types.ValidatorIndex(0), false } return idx, ok } // PubkeyAtIndex returns the pubkey at the given // validator index. func (b *BeaconState) PubkeyAtIndex(idx types.ValidatorIndex) [48]byte { if !b.hasInnerState() { return [48]byte{} } if uint64(idx) >= uint64(len(b.state.Validators)) { return [48]byte{} } b.lock.RLock() defer b.lock.RUnlock() if b.state.Validators[idx] == nil { return [48]byte{} } return bytesutil.ToBytes48(b.state.Validators[idx].PublicKey) } // NumValidators returns the size of the validator registry. func (b *BeaconState) NumValidators() int { if !b.hasInnerState() { return 0 } b.lock.RLock() defer b.lock.RUnlock() return len(b.state.Validators) } // ReadFromEveryValidator reads values from every validator and applies it to the provided function. // Warning: This method is potentially unsafe, as it exposes the actual validator registry. func (b *BeaconState) ReadFromEveryValidator(f func(idx int, val state.ReadOnlyValidator) error) error { if !b.hasInnerState() { return ErrNilInnerState } if b.state.Validators == nil { return errors.New("nil validators in state") } b.lock.RLock() validators := b.state.Validators b.lock.RUnlock() for i, v := range validators { v, err := v1.NewValidator(v) if err != nil { return err } if err := f(i, v); err != nil { return err } } return nil } // Balances of validators participating in consensus on the beacon chain. func (b *BeaconState) Balances() []uint64 { if !b.hasInnerState() { return nil } if b.state.Balances == nil { return nil } b.lock.RLock() defer b.lock.RUnlock() return b.balances() } // balances of validators participating in consensus on the beacon chain. // This assumes that a lock is already held on BeaconState. func (b *BeaconState) balances() []uint64 { if !b.hasInnerState() { return nil } if b.state.Balances == nil { return nil } res := make([]uint64, len(b.state.Balances)) copy(res, b.state.Balances) return res } // BalanceAtIndex of validator with the provided index. func (b *BeaconState) BalanceAtIndex(idx types.ValidatorIndex) (uint64, error) { if !b.hasInnerState() { return 0, ErrNilInnerState } if b.state.Balances == nil { return 0, nil } b.lock.RLock() defer b.lock.RUnlock() if uint64(len(b.state.Balances)) <= uint64(idx) { return 0, fmt.Errorf("index of %d does not exist", idx) } return b.state.Balances[idx], nil } // BalancesLength returns the length of the balances slice. func (b *BeaconState) BalancesLength() int { if !b.hasInnerState() { return 0 } if b.state.Balances == nil { return 0 } b.lock.RLock() defer b.lock.RUnlock() return b.balancesLength() } // Slashings of validators on the beacon chain. func (b *BeaconState) Slashings() []uint64 { if !b.hasInnerState() { return nil } if b.state.Slashings == nil { return nil } b.lock.RLock() defer b.lock.RUnlock() return b.slashings() } // slashings of validators on the beacon chain. // This assumes that a lock is already held on BeaconState. func (b *BeaconState) slashings() []uint64 { if !b.hasInnerState() { return nil } if b.state.Slashings == nil { return nil } res := make([]uint64, len(b.state.Slashings)) copy(res, b.state.Slashings) return res } // inactivityScores of validators participating in consensus on the beacon chain. // This assumes that a lock is already held on BeaconState. func (b *BeaconState) inactivityScores() []uint64 { if !b.hasInnerState() { return nil } if b.state.InactivityScores == nil { return nil } res := make([]uint64, len(b.state.InactivityScores)) copy(res, b.state.InactivityScores) return res } // InactivityScores of validators participating in consensus on the beacon chain. func (b *BeaconState) InactivityScores() ([]uint64, error) { if !b.hasInnerState() { return nil, nil } if b.state.InactivityScores == nil { return nil, nil } b.lock.RLock() defer b.lock.RUnlock() return b.inactivityScores(), nil }