mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-09 13:28:01 -05:00
Altair: Split state getters and setters into its own file (#8746)
* Categorize getters and setters into its own file * Go fmt
This commit is contained in:
@@ -6,14 +6,25 @@ go_library(
|
||||
srcs = [
|
||||
"cloners.go",
|
||||
"doc.go",
|
||||
"field_root_attestation.go",
|
||||
"field_root_eth1.go",
|
||||
"field_root_validator.go",
|
||||
"field_root_vector.go",
|
||||
"field_roots.go",
|
||||
"field_trie.go",
|
||||
"getters.go",
|
||||
"setters.go",
|
||||
"field_trie_helpers.go",
|
||||
"getters_attestation.go",
|
||||
"getters_block.go",
|
||||
"getters_checkpoint.go",
|
||||
"getters_eth1.go",
|
||||
"getters_misc.go",
|
||||
"getters_randao.go",
|
||||
"getters_state.go",
|
||||
"getters_validator.go",
|
||||
"setters_attestation.go",
|
||||
"setters_block.go",
|
||||
"setters_checkpoint.go",
|
||||
"setters_eth1.go",
|
||||
"setters_misc.go",
|
||||
"setters_randao.go",
|
||||
"setters_state.go",
|
||||
"setters_validator.go",
|
||||
"state_trie.go",
|
||||
"types.go",
|
||||
"validator_getters.go",
|
||||
@@ -61,7 +72,7 @@ go_test(
|
||||
"getters_test.go",
|
||||
"helpers_test.go",
|
||||
"references_test.go",
|
||||
"setters_test.go",
|
||||
"setters_attestation_test.go",
|
||||
"state_test.go",
|
||||
"state_trie_test.go",
|
||||
"types_test.go",
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
package stateV0
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/htrutils"
|
||||
)
|
||||
|
||||
// eth1Root computes the HashTreeRoot Merkleization of
|
||||
// a BeaconBlockHeader struct according to the eth2
|
||||
// Simple Serialize specification.
|
||||
func eth1Root(hasher htrutils.HashFn, eth1Data *ethpb.Eth1Data) ([32]byte, error) {
|
||||
if eth1Data == nil {
|
||||
return [32]byte{}, errors.New("nil eth1 data")
|
||||
}
|
||||
|
||||
enc := stateutil.Eth1DataEncKey(eth1Data)
|
||||
if featureconfig.Get().EnableSSZCache {
|
||||
if found, ok := cachedHasher.rootsCache.Get(string(enc)); ok && found != nil {
|
||||
return found.([32]byte), nil
|
||||
}
|
||||
}
|
||||
|
||||
root, err := stateutil.Eth1DataRootWithHasher(hasher, eth1Data)
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
|
||||
if featureconfig.Get().EnableSSZCache {
|
||||
cachedHasher.rootsCache.Set(string(enc), root, 32)
|
||||
}
|
||||
return root, nil
|
||||
}
|
||||
|
||||
// eth1DataVotesRoot computes the HashTreeRoot Merkleization of
|
||||
// a list of Eth1Data structs according to the eth2
|
||||
// Simple Serialize specification.
|
||||
func eth1DataVotesRoot(eth1DataVotes []*ethpb.Eth1Data) ([32]byte, error) {
|
||||
hashKey, err := stateutil.Eth1DatasEncKey(eth1DataVotes)
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
|
||||
if featureconfig.Get().EnableSSZCache {
|
||||
if found, ok := cachedHasher.rootsCache.Get(string(hashKey[:])); ok && found != nil {
|
||||
return found.([32]byte), nil
|
||||
}
|
||||
}
|
||||
root, err := stateutil.Eth1DatasRoot(eth1DataVotes)
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
if featureconfig.Get().EnableSSZCache {
|
||||
cachedHasher.rootsCache.Set(string(hashKey[:]), root, 32)
|
||||
}
|
||||
return root, nil
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
package stateV0
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/hashutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/htrutils"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
)
|
||||
|
||||
func (h *stateRootHasher) validatorRegistryRoot(validators []*ethpb.Validator) ([32]byte, error) {
|
||||
hashKeyElements := make([]byte, len(validators)*32)
|
||||
roots := make([][32]byte, len(validators))
|
||||
emptyKey := hashutil.FastSum256(hashKeyElements)
|
||||
hasher := hashutil.CustomSHA256Hasher()
|
||||
bytesProcessed := 0
|
||||
for i := 0; i < len(validators); i++ {
|
||||
val, err := h.validatorRoot(hasher, validators[i])
|
||||
if err != nil {
|
||||
return [32]byte{}, errors.Wrap(err, "could not compute validators merkleization")
|
||||
}
|
||||
copy(hashKeyElements[bytesProcessed:bytesProcessed+32], val[:])
|
||||
roots[i] = val
|
||||
bytesProcessed += 32
|
||||
}
|
||||
|
||||
hashKey := hashutil.FastSum256(hashKeyElements)
|
||||
if hashKey != emptyKey && h.rootsCache != nil {
|
||||
if found, ok := h.rootsCache.Get(string(hashKey[:])); found != nil && ok {
|
||||
return found.([32]byte), nil
|
||||
}
|
||||
}
|
||||
|
||||
validatorsRootsRoot, err := htrutils.BitwiseMerkleizeArrays(hasher, roots, uint64(len(roots)), params.BeaconConfig().ValidatorRegistryLimit)
|
||||
if err != nil {
|
||||
return [32]byte{}, errors.Wrap(err, "could not compute validator registry merkleization")
|
||||
}
|
||||
validatorsRootsBuf := new(bytes.Buffer)
|
||||
if err := binary.Write(validatorsRootsBuf, binary.LittleEndian, uint64(len(validators))); err != nil {
|
||||
return [32]byte{}, errors.Wrap(err, "could not marshal validator registry length")
|
||||
}
|
||||
// We need to mix in the length of the slice.
|
||||
var validatorsRootsBufRoot [32]byte
|
||||
copy(validatorsRootsBufRoot[:], validatorsRootsBuf.Bytes())
|
||||
res := htrutils.MixInLength(validatorsRootsRoot, validatorsRootsBufRoot[:])
|
||||
if hashKey != emptyKey && h.rootsCache != nil {
|
||||
h.rootsCache.Set(string(hashKey[:]), res, 32)
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (h *stateRootHasher) validatorRoot(hasher htrutils.HashFn, validator *ethpb.Validator) ([32]byte, error) {
|
||||
if validator == nil {
|
||||
return [32]byte{}, errors.New("nil validator")
|
||||
}
|
||||
|
||||
enc := stateutil.ValidatorEncKey(validator)
|
||||
// Check if it exists in cache:
|
||||
if h.rootsCache != nil {
|
||||
if found, ok := h.rootsCache.Get(string(enc)); found != nil && ok {
|
||||
return found.([32]byte), nil
|
||||
}
|
||||
}
|
||||
|
||||
valRoot, err := stateutil.ValidatorRootWithHasher(hasher, validator)
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
|
||||
if h.rootsCache != nil {
|
||||
h.rootsCache.Set(string(enc), valRoot, 32)
|
||||
}
|
||||
return valRoot, nil
|
||||
}
|
||||
|
||||
// ValidatorRegistryRoot computes the HashTreeRoot Merkleization of
|
||||
// a list of validator structs according to the eth2
|
||||
// Simple Serialize specification.
|
||||
func ValidatorRegistryRoot(vals []*ethpb.Validator) ([32]byte, error) {
|
||||
if featureconfig.Get().EnableSSZCache {
|
||||
return cachedHasher.validatorRegistryRoot(vals)
|
||||
}
|
||||
return nocachedHasher.validatorRegistryRoot(vals)
|
||||
}
|
||||
@@ -1,15 +1,11 @@
|
||||
package stateV0
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sync"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/hashutil"
|
||||
)
|
||||
|
||||
// FieldTrie is the representation of the representative
|
||||
@@ -19,6 +15,7 @@ type FieldTrie struct {
|
||||
reference *stateutil.Reference
|
||||
fieldLayers [][]*[32]byte
|
||||
field fieldIndex
|
||||
length uint64
|
||||
}
|
||||
|
||||
// NewFieldTrie is the constructor for the field trie data structure. It creates the corresponding
|
||||
@@ -30,6 +27,7 @@ func NewFieldTrie(field fieldIndex, elements interface{}, length uint64) (*Field
|
||||
field: field,
|
||||
reference: stateutil.NewRef(1),
|
||||
RWMutex: new(sync.RWMutex),
|
||||
length: length,
|
||||
}, nil
|
||||
}
|
||||
datType, ok := fieldMap[field]
|
||||
@@ -40,6 +38,9 @@ func NewFieldTrie(field fieldIndex, elements interface{}, length uint64) (*Field
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := validateElements(field, elements, length); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch datType {
|
||||
case basicArray:
|
||||
return &FieldTrie{
|
||||
@@ -47,6 +48,7 @@ func NewFieldTrie(field fieldIndex, elements interface{}, length uint64) (*Field
|
||||
field: field,
|
||||
reference: stateutil.NewRef(1),
|
||||
RWMutex: new(sync.RWMutex),
|
||||
length: length,
|
||||
}, nil
|
||||
case compositeArray:
|
||||
return &FieldTrie{
|
||||
@@ -54,6 +56,7 @@ func NewFieldTrie(field fieldIndex, elements interface{}, length uint64) (*Field
|
||||
field: field,
|
||||
reference: stateutil.NewRef(1),
|
||||
RWMutex: new(sync.RWMutex),
|
||||
length: length,
|
||||
}, nil
|
||||
default:
|
||||
return nil, errors.Errorf("unrecognized data type in field map: %v", reflect.TypeOf(datType).Name())
|
||||
@@ -79,6 +82,9 @@ func (f *FieldTrie) RecomputeTrie(indices []uint64, elements interface{}) ([32]b
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
if err := f.validateIndices(indices); err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
switch datType {
|
||||
case basicArray:
|
||||
fieldRoot, f.fieldLayers, err = stateutil.RecomputeFromLayer(fieldRoots, indices, f.fieldLayers)
|
||||
@@ -106,6 +112,7 @@ func (f *FieldTrie) CopyTrie() *FieldTrie {
|
||||
field: f.field,
|
||||
reference: stateutil.NewRef(1),
|
||||
RWMutex: new(sync.RWMutex),
|
||||
length: f.length,
|
||||
}
|
||||
}
|
||||
dstFieldTrie := make([][]*[32]byte, len(f.fieldLayers))
|
||||
@@ -118,6 +125,7 @@ func (f *FieldTrie) CopyTrie() *FieldTrie {
|
||||
field: f.field,
|
||||
reference: stateutil.NewRef(1),
|
||||
RWMutex: new(sync.RWMutex),
|
||||
length: f.length,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,115 +145,3 @@ func (f *FieldTrie) TrieRoot() ([32]byte, error) {
|
||||
return [32]byte{}, errors.Errorf("unrecognized data type in field map: %v", reflect.TypeOf(datType).Name())
|
||||
}
|
||||
}
|
||||
|
||||
// this converts the corresponding field and the provided elements to the appropriate roots.
|
||||
func fieldConverters(field fieldIndex, indices []uint64, elements interface{}, convertAll bool) ([][32]byte, error) {
|
||||
switch field {
|
||||
case blockRoots, stateRoots, randaoMixes:
|
||||
val, ok := elements.([][]byte)
|
||||
if !ok {
|
||||
return nil, errors.Errorf("Wanted type of %v but got %v",
|
||||
reflect.TypeOf([][]byte{}).Name(), reflect.TypeOf(elements).Name())
|
||||
}
|
||||
return stateutil.HandleByteArrays(val, indices, convertAll)
|
||||
case eth1DataVotes:
|
||||
val, ok := elements.([]*ethpb.Eth1Data)
|
||||
if !ok {
|
||||
return nil, errors.Errorf("Wanted type of %v but got %v",
|
||||
reflect.TypeOf([]*ethpb.Eth1Data{}).Name(), reflect.TypeOf(elements).Name())
|
||||
}
|
||||
return handleEth1DataSlice(val, indices, convertAll)
|
||||
case validators:
|
||||
val, ok := elements.([]*ethpb.Validator)
|
||||
if !ok {
|
||||
return nil, errors.Errorf("Wanted type of %v but got %v",
|
||||
reflect.TypeOf([]*ethpb.Validator{}).Name(), reflect.TypeOf(elements).Name())
|
||||
}
|
||||
return stateutil.HandleValidatorSlice(val, indices, convertAll)
|
||||
case previousEpochAttestations, currentEpochAttestations:
|
||||
val, ok := elements.([]*pb.PendingAttestation)
|
||||
if !ok {
|
||||
return nil, errors.Errorf("Wanted type of %v but got %v",
|
||||
reflect.TypeOf([]*pb.PendingAttestation{}).Name(), reflect.TypeOf(elements).Name())
|
||||
}
|
||||
return handlePendingAttestation(val, indices, convertAll)
|
||||
default:
|
||||
return [][32]byte{}, errors.Errorf("got unsupported type of %v", reflect.TypeOf(elements).Name())
|
||||
}
|
||||
}
|
||||
|
||||
func handleEth1DataSlice(val []*ethpb.Eth1Data, indices []uint64, convertAll bool) ([][32]byte, error) {
|
||||
length := len(indices)
|
||||
if convertAll {
|
||||
length = len(val)
|
||||
}
|
||||
roots := make([][32]byte, 0, length)
|
||||
hasher := hashutil.CustomSHA256Hasher()
|
||||
rootCreator := func(input *ethpb.Eth1Data) error {
|
||||
newRoot, err := eth1Root(hasher, input)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
roots = append(roots, newRoot)
|
||||
return nil
|
||||
}
|
||||
if convertAll {
|
||||
for i := range val {
|
||||
err := rootCreator(val[i])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
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 items in eth1 data slice %d", idx, len(val))
|
||||
}
|
||||
err := rootCreator(val[idx])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
return roots, nil
|
||||
}
|
||||
|
||||
func handlePendingAttestation(val []*pb.PendingAttestation, indices []uint64, convertAll bool) ([][32]byte, error) {
|
||||
length := len(indices)
|
||||
if convertAll {
|
||||
length = len(val)
|
||||
}
|
||||
roots := make([][32]byte, 0, length)
|
||||
hasher := hashutil.CustomSHA256Hasher()
|
||||
rootCreator := func(input *pb.PendingAttestation) error {
|
||||
newRoot, err := stateutil.PendingAttRootWithHasher(hasher, input)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
roots = append(roots, newRoot)
|
||||
return nil
|
||||
}
|
||||
if convertAll {
|
||||
for i := range val {
|
||||
err := rootCreator(val[i])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
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 pending attestations %d", idx, len(val))
|
||||
}
|
||||
err := rootCreator(val[idx])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
return roots, nil
|
||||
}
|
||||
|
||||
141
beacon-chain/state/stateV0/field_trie_helpers.go
Normal file
141
beacon-chain/state/stateV0/field_trie_helpers.go
Normal file
@@ -0,0 +1,141 @@
|
||||
package stateV0
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/hashutil"
|
||||
)
|
||||
|
||||
func (f *FieldTrie) validateIndices(idxs []uint64) error {
|
||||
for _, idx := range idxs {
|
||||
if idx >= f.length {
|
||||
return errors.Errorf("invalid index for field %s: %d >= length %d", f.field.String(), idx, f.length)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateElements(field fieldIndex, elements interface{}, length uint64) error {
|
||||
val := reflect.ValueOf(elements)
|
||||
if val.Len() > int(length) {
|
||||
return errors.Errorf("elements length is larger than expected for field %s: %d > %d", field.String(), val.Len(), length)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// this converts the corresponding field and the provided elements to the appropriate roots.
|
||||
func fieldConverters(field fieldIndex, indices []uint64, elements interface{}, convertAll bool) ([][32]byte, error) {
|
||||
switch field {
|
||||
case blockRoots, stateRoots, randaoMixes:
|
||||
val, ok := elements.([][]byte)
|
||||
if !ok {
|
||||
return nil, errors.Errorf("Wanted type of %v but got %v",
|
||||
reflect.TypeOf([][]byte{}).Name(), reflect.TypeOf(elements).Name())
|
||||
}
|
||||
return stateutil.HandleByteArrays(val, indices, convertAll)
|
||||
case eth1DataVotes:
|
||||
val, ok := elements.([]*ethpb.Eth1Data)
|
||||
if !ok {
|
||||
return nil, errors.Errorf("Wanted type of %v but got %v",
|
||||
reflect.TypeOf([]*ethpb.Eth1Data{}).Name(), reflect.TypeOf(elements).Name())
|
||||
}
|
||||
return handleEth1DataSlice(val, indices, convertAll)
|
||||
case validators:
|
||||
val, ok := elements.([]*ethpb.Validator)
|
||||
if !ok {
|
||||
return nil, errors.Errorf("Wanted type of %v but got %v",
|
||||
reflect.TypeOf([]*ethpb.Validator{}).Name(), reflect.TypeOf(elements).Name())
|
||||
}
|
||||
return stateutil.HandleValidatorSlice(val, indices, convertAll)
|
||||
case previousEpochAttestations, currentEpochAttestations:
|
||||
val, ok := elements.([]*pb.PendingAttestation)
|
||||
if !ok {
|
||||
return nil, errors.Errorf("Wanted type of %v but got %v",
|
||||
reflect.TypeOf([]*pb.PendingAttestation{}).Name(), reflect.TypeOf(elements).Name())
|
||||
}
|
||||
return handlePendingAttestation(val, indices, convertAll)
|
||||
default:
|
||||
return [][32]byte{}, errors.Errorf("got unsupported type of %v", reflect.TypeOf(elements).Name())
|
||||
}
|
||||
}
|
||||
|
||||
func handleEth1DataSlice(val []*ethpb.Eth1Data, indices []uint64, convertAll bool) ([][32]byte, error) {
|
||||
length := len(indices)
|
||||
if convertAll {
|
||||
length = len(val)
|
||||
}
|
||||
roots := make([][32]byte, 0, length)
|
||||
hasher := hashutil.CustomSHA256Hasher()
|
||||
rootCreator := func(input *ethpb.Eth1Data) error {
|
||||
newRoot, err := eth1Root(hasher, input)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
roots = append(roots, newRoot)
|
||||
return nil
|
||||
}
|
||||
if convertAll {
|
||||
for i := range val {
|
||||
err := rootCreator(val[i])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
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 items in eth1 data slice %d", idx, len(val))
|
||||
}
|
||||
err := rootCreator(val[idx])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
return roots, nil
|
||||
}
|
||||
|
||||
func handlePendingAttestation(val []*pb.PendingAttestation, indices []uint64, convertAll bool) ([][32]byte, error) {
|
||||
length := len(indices)
|
||||
if convertAll {
|
||||
length = len(val)
|
||||
}
|
||||
roots := make([][32]byte, 0, length)
|
||||
hasher := hashutil.CustomSHA256Hasher()
|
||||
rootCreator := func(input *pb.PendingAttestation) error {
|
||||
newRoot, err := stateutil.PendingAttRootWithHasher(hasher, input)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
roots = append(roots, newRoot)
|
||||
return nil
|
||||
}
|
||||
if convertAll {
|
||||
for i := range val {
|
||||
err := rootCreator(val[i])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
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 pending attestations %d", idx, len(val))
|
||||
}
|
||||
err := rootCreator(val[idx])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
return roots, nil
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -3,16 +3,72 @@ package stateV0
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/hashutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/htrutils"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
)
|
||||
|
||||
func (h *stateRootHasher) epochAttestationsRoot(atts []*pb.PendingAttestation) ([32]byte, error) {
|
||||
// PreviousEpochAttestations corresponding to blocks on the beacon chain.
|
||||
func (b *BeaconState) PreviousEpochAttestations() ([]*pbp2p.PendingAttestation, error) {
|
||||
if !b.hasInnerState() {
|
||||
return nil, nil
|
||||
}
|
||||
if b.state.PreviousEpochAttestations == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
return b.previousEpochAttestations(), nil
|
||||
}
|
||||
|
||||
// previousEpochAttestations corresponding to blocks on the beacon chain.
|
||||
// This assumes that a lock is already held on BeaconState.
|
||||
func (b *BeaconState) previousEpochAttestations() []*pbp2p.PendingAttestation {
|
||||
if !b.hasInnerState() {
|
||||
return nil
|
||||
}
|
||||
|
||||
return b.safeCopyPendingAttestationSlice(b.state.PreviousEpochAttestations)
|
||||
}
|
||||
|
||||
// CurrentEpochAttestations corresponding to blocks on the beacon chain.
|
||||
func (b *BeaconState) CurrentEpochAttestations() ([]*pbp2p.PendingAttestation, error) {
|
||||
if !b.hasInnerState() {
|
||||
return nil, nil
|
||||
}
|
||||
if b.state.CurrentEpochAttestations == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
return b.currentEpochAttestations(), nil
|
||||
}
|
||||
|
||||
// currentEpochAttestations corresponding to blocks on the beacon chain.
|
||||
// This assumes that a lock is already held on BeaconState.
|
||||
func (b *BeaconState) currentEpochAttestations() []*pbp2p.PendingAttestation {
|
||||
if !b.hasInnerState() {
|
||||
return nil
|
||||
}
|
||||
|
||||
return b.safeCopyPendingAttestationSlice(b.state.CurrentEpochAttestations)
|
||||
}
|
||||
|
||||
func (h *stateRootHasher) epochAttestationsRoot(atts []*pbp2p.PendingAttestation) ([32]byte, error) {
|
||||
max := uint64(params.BeaconConfig().SlotsPerEpoch) * params.BeaconConfig().MaxAttestations
|
||||
if uint64(len(atts)) > max {
|
||||
return [32]byte{}, fmt.Errorf("epoch attestation exceeds max length %d", max)
|
||||
}
|
||||
|
||||
hasher := hashutil.CustomSHA256Hasher()
|
||||
roots := make([][]byte, len(atts))
|
||||
for i := 0; i < len(atts); i++ {
|
||||
@@ -43,7 +99,7 @@ func (h *stateRootHasher) epochAttestationsRoot(atts []*pb.PendingAttestation) (
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (h *stateRootHasher) pendingAttestationRoot(hasher htrutils.HashFn, att *pb.PendingAttestation) ([32]byte, error) {
|
||||
func (h *stateRootHasher) pendingAttestationRoot(hasher htrutils.HashFn, att *pbp2p.PendingAttestation) ([32]byte, error) {
|
||||
if att == nil {
|
||||
return [32]byte{}, errors.New("nil pending attestation")
|
||||
}
|
||||
96
beacon-chain/state/stateV0/getters_block.go
Normal file
96
beacon-chain/state/stateV0/getters_block.go
Normal file
@@ -0,0 +1,96 @@
|
||||
package stateV0
|
||||
|
||||
import ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
|
||||
// LatestBlockHeader stored within the beacon state.
|
||||
func (b *BeaconState) LatestBlockHeader() *ethpb.BeaconBlockHeader {
|
||||
if !b.hasInnerState() {
|
||||
return nil
|
||||
}
|
||||
if b.state.LatestBlockHeader == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
return b.latestBlockHeader()
|
||||
}
|
||||
|
||||
// latestBlockHeader stored within the beacon state.
|
||||
// This assumes that a lock is already held on BeaconState.
|
||||
func (b *BeaconState) latestBlockHeader() *ethpb.BeaconBlockHeader {
|
||||
if !b.hasInnerState() {
|
||||
return nil
|
||||
}
|
||||
if b.state.LatestBlockHeader == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
hdr := ðpb.BeaconBlockHeader{
|
||||
Slot: b.state.LatestBlockHeader.Slot,
|
||||
ProposerIndex: b.state.LatestBlockHeader.ProposerIndex,
|
||||
}
|
||||
|
||||
parentRoot := make([]byte, len(b.state.LatestBlockHeader.ParentRoot))
|
||||
bodyRoot := make([]byte, len(b.state.LatestBlockHeader.BodyRoot))
|
||||
stateRoot := make([]byte, len(b.state.LatestBlockHeader.StateRoot))
|
||||
|
||||
copy(parentRoot, b.state.LatestBlockHeader.ParentRoot)
|
||||
copy(bodyRoot, b.state.LatestBlockHeader.BodyRoot)
|
||||
copy(stateRoot, b.state.LatestBlockHeader.StateRoot)
|
||||
hdr.ParentRoot = parentRoot
|
||||
hdr.BodyRoot = bodyRoot
|
||||
hdr.StateRoot = stateRoot
|
||||
return hdr
|
||||
}
|
||||
|
||||
// BlockRoots kept track of in the beacon state.
|
||||
func (b *BeaconState) BlockRoots() [][]byte {
|
||||
if !b.hasInnerState() {
|
||||
return nil
|
||||
}
|
||||
if b.state.BlockRoots == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
return b.blockRoots()
|
||||
}
|
||||
|
||||
// blockRoots kept track of in the beacon state.
|
||||
// This assumes that a lock is already held on BeaconState.
|
||||
func (b *BeaconState) blockRoots() [][]byte {
|
||||
if !b.hasInnerState() {
|
||||
return nil
|
||||
}
|
||||
return b.safeCopy2DByteSlice(b.state.BlockRoots)
|
||||
}
|
||||
|
||||
// BlockRootAtIndex retrieves a specific block root based on an
|
||||
// input index value.
|
||||
func (b *BeaconState) BlockRootAtIndex(idx uint64) ([]byte, error) {
|
||||
if !b.hasInnerState() {
|
||||
return nil, ErrNilInnerState
|
||||
}
|
||||
if b.state.BlockRoots == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
return b.blockRootAtIndex(idx)
|
||||
}
|
||||
|
||||
// blockRootAtIndex retrieves a specific block root based on an
|
||||
// input index value.
|
||||
// This assumes that a lock is already held on BeaconState.
|
||||
func (b *BeaconState) blockRootAtIndex(idx uint64) ([]byte, error) {
|
||||
if !b.hasInnerState() {
|
||||
return nil, ErrNilInnerState
|
||||
}
|
||||
return b.safeCopyBytesAtIndex(b.state.BlockRoots, idx)
|
||||
}
|
||||
160
beacon-chain/state/stateV0/getters_checkpoint.go
Normal file
160
beacon-chain/state/stateV0/getters_checkpoint.go
Normal file
@@ -0,0 +1,160 @@
|
||||
package stateV0
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/go-bitfield"
|
||||
)
|
||||
|
||||
// JustificationBits marking which epochs have been justified in the beacon chain.
|
||||
func (b *BeaconState) JustificationBits() bitfield.Bitvector4 {
|
||||
if !b.hasInnerState() {
|
||||
return nil
|
||||
}
|
||||
if b.state.JustificationBits == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
return b.justificationBits()
|
||||
}
|
||||
|
||||
// justificationBits marking which epochs have been justified in the beacon chain.
|
||||
// This assumes that a lock is already held on BeaconState.
|
||||
func (b *BeaconState) justificationBits() bitfield.Bitvector4 {
|
||||
if !b.hasInnerState() {
|
||||
return nil
|
||||
}
|
||||
if b.state.JustificationBits == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
res := make([]byte, len(b.state.JustificationBits.Bytes()))
|
||||
copy(res, b.state.JustificationBits.Bytes())
|
||||
return res
|
||||
}
|
||||
|
||||
// PreviousJustifiedCheckpoint denoting an epoch and block root.
|
||||
func (b *BeaconState) PreviousJustifiedCheckpoint() *ethpb.Checkpoint {
|
||||
if !b.hasInnerState() {
|
||||
return nil
|
||||
}
|
||||
if b.state.PreviousJustifiedCheckpoint == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
return b.previousJustifiedCheckpoint()
|
||||
}
|
||||
|
||||
// previousJustifiedCheckpoint denoting an epoch and block root.
|
||||
// This assumes that a lock is already held on BeaconState.
|
||||
func (b *BeaconState) previousJustifiedCheckpoint() *ethpb.Checkpoint {
|
||||
if !b.hasInnerState() {
|
||||
return nil
|
||||
}
|
||||
|
||||
return b.safeCopyCheckpoint(b.state.PreviousJustifiedCheckpoint)
|
||||
}
|
||||
|
||||
// CurrentJustifiedCheckpoint denoting an epoch and block root.
|
||||
func (b *BeaconState) CurrentJustifiedCheckpoint() *ethpb.Checkpoint {
|
||||
if !b.hasInnerState() {
|
||||
return nil
|
||||
}
|
||||
if b.state.CurrentJustifiedCheckpoint == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
return b.currentJustifiedCheckpoint()
|
||||
}
|
||||
|
||||
// currentJustifiedCheckpoint denoting an epoch and block root.
|
||||
// This assumes that a lock is already held on BeaconState.
|
||||
func (b *BeaconState) currentJustifiedCheckpoint() *ethpb.Checkpoint {
|
||||
if !b.hasInnerState() {
|
||||
return nil
|
||||
}
|
||||
|
||||
return b.safeCopyCheckpoint(b.state.CurrentJustifiedCheckpoint)
|
||||
}
|
||||
|
||||
// MatchCurrentJustifiedCheckpoint returns true if input justified checkpoint matches
|
||||
// the current justified checkpoint in state.
|
||||
func (b *BeaconState) MatchCurrentJustifiedCheckpoint(c *ethpb.Checkpoint) bool {
|
||||
if !b.hasInnerState() {
|
||||
return false
|
||||
}
|
||||
if b.state.CurrentJustifiedCheckpoint == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if c.Epoch != b.state.CurrentJustifiedCheckpoint.Epoch {
|
||||
return false
|
||||
}
|
||||
return bytes.Equal(c.Root, b.state.CurrentJustifiedCheckpoint.Root)
|
||||
}
|
||||
|
||||
// MatchPreviousJustifiedCheckpoint returns true if the input justified checkpoint matches
|
||||
// the previous justified checkpoint in state.
|
||||
func (b *BeaconState) MatchPreviousJustifiedCheckpoint(c *ethpb.Checkpoint) bool {
|
||||
if !b.hasInnerState() {
|
||||
return false
|
||||
}
|
||||
if b.state.PreviousJustifiedCheckpoint == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if c.Epoch != b.state.PreviousJustifiedCheckpoint.Epoch {
|
||||
return false
|
||||
}
|
||||
return bytes.Equal(c.Root, b.state.PreviousJustifiedCheckpoint.Root)
|
||||
}
|
||||
|
||||
// FinalizedCheckpoint denoting an epoch and block root.
|
||||
func (b *BeaconState) FinalizedCheckpoint() *ethpb.Checkpoint {
|
||||
if !b.hasInnerState() {
|
||||
return nil
|
||||
}
|
||||
if b.state.FinalizedCheckpoint == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
return b.finalizedCheckpoint()
|
||||
}
|
||||
|
||||
// finalizedCheckpoint denoting an epoch and block root.
|
||||
// This assumes that a lock is already held on BeaconState.
|
||||
func (b *BeaconState) finalizedCheckpoint() *ethpb.Checkpoint {
|
||||
if !b.hasInnerState() {
|
||||
return nil
|
||||
}
|
||||
|
||||
return b.safeCopyCheckpoint(b.state.FinalizedCheckpoint)
|
||||
}
|
||||
|
||||
// FinalizedCheckpointEpoch returns the epoch value of the finalized checkpoint.
|
||||
func (b *BeaconState) FinalizedCheckpointEpoch() types.Epoch {
|
||||
if !b.hasInnerState() {
|
||||
return 0
|
||||
}
|
||||
if b.state.FinalizedCheckpoint == nil {
|
||||
return 0
|
||||
}
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
return b.state.FinalizedCheckpoint.Epoch
|
||||
}
|
||||
145
beacon-chain/state/stateV0/getters_eth1.go
Normal file
145
beacon-chain/state/stateV0/getters_eth1.go
Normal file
@@ -0,0 +1,145 @@
|
||||
package stateV0
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/htrutils"
|
||||
)
|
||||
|
||||
// Eth1Data corresponding to the proof-of-work chain information stored in the beacon state.
|
||||
func (b *BeaconState) Eth1Data() *ethpb.Eth1Data {
|
||||
if !b.hasInnerState() {
|
||||
return nil
|
||||
}
|
||||
if b.state.Eth1Data == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
return b.eth1Data()
|
||||
}
|
||||
|
||||
// eth1Data corresponding to the proof-of-work chain information stored in the beacon state.
|
||||
// This assumes that a lock is already held on BeaconState.
|
||||
func (b *BeaconState) eth1Data() *ethpb.Eth1Data {
|
||||
if !b.hasInnerState() {
|
||||
return nil
|
||||
}
|
||||
if b.state.Eth1Data == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return CopyETH1Data(b.state.Eth1Data)
|
||||
}
|
||||
|
||||
// Eth1DataVotes corresponds to votes from eth2 on the canonical proof-of-work chain
|
||||
// data retrieved from eth1.
|
||||
func (b *BeaconState) Eth1DataVotes() []*ethpb.Eth1Data {
|
||||
if !b.hasInnerState() {
|
||||
return nil
|
||||
}
|
||||
if b.state.Eth1DataVotes == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
return b.eth1DataVotes()
|
||||
}
|
||||
|
||||
// eth1DataVotes corresponds to votes from eth2 on the canonical proof-of-work chain
|
||||
// data retrieved from eth1.
|
||||
// This assumes that a lock is already held on BeaconState.
|
||||
func (b *BeaconState) eth1DataVotes() []*ethpb.Eth1Data {
|
||||
if !b.hasInnerState() {
|
||||
return nil
|
||||
}
|
||||
if b.state.Eth1DataVotes == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
res := make([]*ethpb.Eth1Data, len(b.state.Eth1DataVotes))
|
||||
for i := 0; i < len(res); i++ {
|
||||
res[i] = CopyETH1Data(b.state.Eth1DataVotes[i])
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// Eth1DepositIndex corresponds to the index of the deposit made to the
|
||||
// validator deposit contract at the time of this state's eth1 data.
|
||||
func (b *BeaconState) Eth1DepositIndex() uint64 {
|
||||
if !b.hasInnerState() {
|
||||
return 0
|
||||
}
|
||||
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
return b.eth1DepositIndex()
|
||||
}
|
||||
|
||||
// eth1DepositIndex corresponds to the index of the deposit made to the
|
||||
// validator deposit contract at the time of this state's eth1 data.
|
||||
// This assumes that a lock is already held on BeaconState.
|
||||
func (b *BeaconState) eth1DepositIndex() uint64 {
|
||||
if !b.hasInnerState() {
|
||||
return 0
|
||||
}
|
||||
|
||||
return b.state.Eth1DepositIndex
|
||||
}
|
||||
|
||||
// eth1Root computes the HashTreeRoot Merkleization of
|
||||
// a BeaconBlockHeader struct according to the eth2
|
||||
// Simple Serialize specification.
|
||||
func eth1Root(hasher htrutils.HashFn, eth1Data *ethpb.Eth1Data) ([32]byte, error) {
|
||||
if eth1Data == nil {
|
||||
return [32]byte{}, errors.New("nil eth1 data")
|
||||
}
|
||||
|
||||
enc := stateutil.Eth1DataEncKey(eth1Data)
|
||||
if featureconfig.Get().EnableSSZCache {
|
||||
if found, ok := cachedHasher.rootsCache.Get(string(enc)); ok && found != nil {
|
||||
return found.([32]byte), nil
|
||||
}
|
||||
}
|
||||
|
||||
root, err := stateutil.Eth1DataRootWithHasher(hasher, eth1Data)
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
|
||||
if featureconfig.Get().EnableSSZCache {
|
||||
cachedHasher.rootsCache.Set(string(enc), root, 32)
|
||||
}
|
||||
return root, nil
|
||||
}
|
||||
|
||||
// eth1DataVotesRoot computes the HashTreeRoot Merkleization of
|
||||
// a list of Eth1Data structs according to the eth2
|
||||
// Simple Serialize specification.
|
||||
func eth1DataVotesRoot(eth1DataVotes []*ethpb.Eth1Data) ([32]byte, error) {
|
||||
hashKey, err := stateutil.Eth1DatasEncKey(eth1DataVotes)
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
|
||||
if featureconfig.Get().EnableSSZCache {
|
||||
if found, ok := cachedHasher.rootsCache.Get(string(hashKey[:])); ok && found != nil {
|
||||
return found.([32]byte), nil
|
||||
}
|
||||
}
|
||||
root, err := stateutil.Eth1DatasRoot(eth1DataVotes)
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
if featureconfig.Get().EnableSSZCache {
|
||||
cachedHasher.rootsCache.Set(string(hashKey[:]), root, 32)
|
||||
}
|
||||
return root, nil
|
||||
}
|
||||
@@ -2,12 +2,162 @@ package stateV0
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/hashutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/htrutils"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
)
|
||||
|
||||
// GenesisTime of the beacon state as a uint64.
|
||||
func (b *BeaconState) GenesisTime() uint64 {
|
||||
if !b.hasInnerState() {
|
||||
return 0
|
||||
}
|
||||
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
return b.genesisTime()
|
||||
}
|
||||
|
||||
// genesisTime of the beacon state as a uint64.
|
||||
// This assumes that a lock is already held on BeaconState.
|
||||
func (b *BeaconState) genesisTime() uint64 {
|
||||
if !b.hasInnerState() {
|
||||
return 0
|
||||
}
|
||||
|
||||
return b.state.GenesisTime
|
||||
}
|
||||
|
||||
// GenesisValidatorRoot of the beacon state.
|
||||
func (b *BeaconState) GenesisValidatorRoot() []byte {
|
||||
if !b.hasInnerState() {
|
||||
return nil
|
||||
}
|
||||
if b.state.GenesisValidatorsRoot == nil {
|
||||
return params.BeaconConfig().ZeroHash[:]
|
||||
}
|
||||
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
return b.genesisValidatorRoot()
|
||||
}
|
||||
|
||||
// genesisValidatorRoot of the beacon state.
|
||||
// This assumes that a lock is already held on BeaconState.
|
||||
func (b *BeaconState) genesisValidatorRoot() []byte {
|
||||
if !b.hasInnerState() {
|
||||
return nil
|
||||
}
|
||||
if b.state.GenesisValidatorsRoot == nil {
|
||||
return params.BeaconConfig().ZeroHash[:]
|
||||
}
|
||||
|
||||
root := make([]byte, 32)
|
||||
copy(root, b.state.GenesisValidatorsRoot)
|
||||
return root
|
||||
}
|
||||
|
||||
// Slot of the current beacon chain state.
|
||||
func (b *BeaconState) Slot() types.Slot {
|
||||
if !b.hasInnerState() {
|
||||
return 0
|
||||
}
|
||||
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
return b.slot()
|
||||
}
|
||||
|
||||
// slot of the current beacon chain state.
|
||||
// This assumes that a lock is already held on BeaconState.
|
||||
func (b *BeaconState) slot() types.Slot {
|
||||
if !b.hasInnerState() {
|
||||
return 0
|
||||
}
|
||||
|
||||
return b.state.Slot
|
||||
}
|
||||
|
||||
// Fork version of the beacon chain.
|
||||
func (b *BeaconState) Fork() *pbp2p.Fork {
|
||||
if !b.hasInnerState() {
|
||||
return nil
|
||||
}
|
||||
if b.state.Fork == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
return b.fork()
|
||||
}
|
||||
|
||||
// fork version of the beacon chain.
|
||||
// This assumes that a lock is already held on BeaconState.
|
||||
func (b *BeaconState) fork() *pbp2p.Fork {
|
||||
if !b.hasInnerState() {
|
||||
return nil
|
||||
}
|
||||
if b.state.Fork == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
prevVersion := make([]byte, len(b.state.Fork.PreviousVersion))
|
||||
copy(prevVersion, b.state.Fork.PreviousVersion)
|
||||
currVersion := make([]byte, len(b.state.Fork.CurrentVersion))
|
||||
copy(currVersion, b.state.Fork.CurrentVersion)
|
||||
return &pbp2p.Fork{
|
||||
PreviousVersion: prevVersion,
|
||||
CurrentVersion: currVersion,
|
||||
Epoch: b.state.Fork.Epoch,
|
||||
}
|
||||
}
|
||||
|
||||
// HistoricalRoots based on epochs stored in the beacon state.
|
||||
func (b *BeaconState) HistoricalRoots() [][]byte {
|
||||
if !b.hasInnerState() {
|
||||
return nil
|
||||
}
|
||||
if b.state.HistoricalRoots == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
return b.historicalRoots()
|
||||
}
|
||||
|
||||
// historicalRoots based on epochs stored in the beacon state.
|
||||
// This assumes that a lock is already held on BeaconState.
|
||||
func (b *BeaconState) historicalRoots() [][]byte {
|
||||
if !b.hasInnerState() {
|
||||
return nil
|
||||
}
|
||||
return b.safeCopy2DByteSlice(b.state.HistoricalRoots)
|
||||
}
|
||||
|
||||
// balancesLength returns the length of the balances slice.
|
||||
// This assumes that a lock is already held on BeaconState.
|
||||
func (b *BeaconState) balancesLength() int {
|
||||
if !b.hasInnerState() {
|
||||
return 0
|
||||
}
|
||||
if b.state.Balances == nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
return len(b.state.Balances)
|
||||
}
|
||||
|
||||
// RootsArrayHashTreeRoot computes the Merkle root of arrays of 32-byte hashes, such as [64][32]byte
|
||||
// according to the Simple Serialize specification of eth2.
|
||||
func RootsArrayHashTreeRoot(vals [][]byte, length uint64, fieldName string) ([32]byte, error) {
|
||||
81
beacon-chain/state/stateV0/getters_randao.go
Normal file
81
beacon-chain/state/stateV0/getters_randao.go
Normal file
@@ -0,0 +1,81 @@
|
||||
package stateV0
|
||||
|
||||
// RandaoMixes of block proposers on the beacon chain.
|
||||
func (b *BeaconState) RandaoMixes() [][]byte {
|
||||
if !b.hasInnerState() {
|
||||
return nil
|
||||
}
|
||||
if b.state.RandaoMixes == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
return b.randaoMixes()
|
||||
}
|
||||
|
||||
// randaoMixes of block proposers on the beacon chain.
|
||||
// This assumes that a lock is already held on BeaconState.
|
||||
func (b *BeaconState) randaoMixes() [][]byte {
|
||||
if !b.hasInnerState() {
|
||||
return nil
|
||||
}
|
||||
|
||||
return b.safeCopy2DByteSlice(b.state.RandaoMixes)
|
||||
}
|
||||
|
||||
// RandaoMixAtIndex retrieves a specific block root based on an
|
||||
// input index value.
|
||||
func (b *BeaconState) RandaoMixAtIndex(idx uint64) ([]byte, error) {
|
||||
if !b.hasInnerState() {
|
||||
return nil, ErrNilInnerState
|
||||
}
|
||||
if b.state.RandaoMixes == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
return b.randaoMixAtIndex(idx)
|
||||
}
|
||||
|
||||
// randaoMixAtIndex retrieves a specific block root based on an
|
||||
// input index value.
|
||||
// This assumes that a lock is already held on BeaconState.
|
||||
func (b *BeaconState) randaoMixAtIndex(idx uint64) ([]byte, error) {
|
||||
if !b.hasInnerState() {
|
||||
return nil, ErrNilInnerState
|
||||
}
|
||||
|
||||
return b.safeCopyBytesAtIndex(b.state.RandaoMixes, idx)
|
||||
}
|
||||
|
||||
// RandaoMixesLength returns the length of the randao mixes slice.
|
||||
func (b *BeaconState) RandaoMixesLength() int {
|
||||
if !b.hasInnerState() {
|
||||
return 0
|
||||
}
|
||||
if b.state.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 !b.hasInnerState() {
|
||||
return 0
|
||||
}
|
||||
if b.state.RandaoMixes == nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
return len(b.state.RandaoMixes)
|
||||
}
|
||||
172
beacon-chain/state/stateV0/getters_state.go
Normal file
172
beacon-chain/state/stateV0/getters_state.go
Normal file
@@ -0,0 +1,172 @@
|
||||
package stateV0
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
)
|
||||
|
||||
// InnerStateUnsafe returns the pointer value of the underlying
|
||||
// beacon state proto object, bypassing immutability. Use with care.
|
||||
func (b *BeaconState) InnerStateUnsafe() interface{} {
|
||||
if b == nil {
|
||||
return nil
|
||||
}
|
||||
return b.state
|
||||
}
|
||||
|
||||
// CloneInnerState the beacon state into a protobuf for usage.
|
||||
func (b *BeaconState) CloneInnerState() interface{} {
|
||||
if b == nil || b.state == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
return &pbp2p.BeaconState{
|
||||
GenesisTime: b.genesisTime(),
|
||||
GenesisValidatorsRoot: b.genesisValidatorRoot(),
|
||||
Slot: b.slot(),
|
||||
Fork: b.fork(),
|
||||
LatestBlockHeader: b.latestBlockHeader(),
|
||||
BlockRoots: b.blockRoots(),
|
||||
StateRoots: b.stateRoots(),
|
||||
HistoricalRoots: b.historicalRoots(),
|
||||
Eth1Data: b.eth1Data(),
|
||||
Eth1DataVotes: b.eth1DataVotes(),
|
||||
Eth1DepositIndex: b.eth1DepositIndex(),
|
||||
Validators: b.validators(),
|
||||
Balances: b.balances(),
|
||||
RandaoMixes: b.randaoMixes(),
|
||||
Slashings: b.slashings(),
|
||||
PreviousEpochAttestations: b.previousEpochAttestations(),
|
||||
CurrentEpochAttestations: b.currentEpochAttestations(),
|
||||
JustificationBits: b.justificationBits(),
|
||||
PreviousJustifiedCheckpoint: b.previousJustifiedCheckpoint(),
|
||||
CurrentJustifiedCheckpoint: b.currentJustifiedCheckpoint(),
|
||||
FinalizedCheckpoint: b.finalizedCheckpoint(),
|
||||
}
|
||||
}
|
||||
|
||||
// hasInnerState detects if the internal reference to the state data structure
|
||||
// is populated correctly. Returns false if nil.
|
||||
func (b *BeaconState) hasInnerState() bool {
|
||||
return b != nil && b.state != nil
|
||||
}
|
||||
|
||||
// StateRoots kept track of in the beacon state.
|
||||
func (b *BeaconState) StateRoots() [][]byte {
|
||||
if !b.hasInnerState() {
|
||||
return nil
|
||||
}
|
||||
if b.state.StateRoots == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
return b.stateRoots()
|
||||
}
|
||||
|
||||
// StateRoots kept track of in the beacon state.
|
||||
// This assumes that a lock is already held on BeaconState.
|
||||
func (b *BeaconState) stateRoots() [][]byte {
|
||||
if !b.hasInnerState() {
|
||||
return nil
|
||||
}
|
||||
return b.safeCopy2DByteSlice(b.state.StateRoots)
|
||||
}
|
||||
|
||||
// StateRootAtIndex retrieves a specific state root based on an
|
||||
// input index value.
|
||||
func (b *BeaconState) StateRootAtIndex(idx uint64) ([]byte, error) {
|
||||
if !b.hasInnerState() {
|
||||
return nil, ErrNilInnerState
|
||||
}
|
||||
if b.state.StateRoots == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
return b.stateRootAtIndex(idx)
|
||||
}
|
||||
|
||||
// stateRootAtIndex retrieves a specific state root based on an
|
||||
// input index value.
|
||||
// This assumes that a lock is already held on BeaconState.
|
||||
func (b *BeaconState) stateRootAtIndex(idx uint64) ([]byte, error) {
|
||||
if !b.hasInnerState() {
|
||||
return nil, ErrNilInnerState
|
||||
}
|
||||
return b.safeCopyBytesAtIndex(b.state.StateRoots, idx)
|
||||
}
|
||||
|
||||
// MarshalSSZ marshals the underlying beacon state to bytes.
|
||||
func (b *BeaconState) MarshalSSZ() ([]byte, error) {
|
||||
if !b.hasInnerState() {
|
||||
return nil, errors.New("nil beacon state")
|
||||
}
|
||||
return b.state.MarshalSSZ()
|
||||
}
|
||||
|
||||
// ProtobufBeaconState transforms an input into beacon state in the form of protobuf.
|
||||
// Error is returned if the input is not type protobuf beacon state.
|
||||
func ProtobufBeaconState(s interface{}) (*pbp2p.BeaconState, error) {
|
||||
pbState, ok := s.(*pbp2p.BeaconState)
|
||||
if !ok {
|
||||
return nil, errors.New("input is not type pb.BeaconState")
|
||||
}
|
||||
return pbState, nil
|
||||
}
|
||||
|
||||
func (b *BeaconState) safeCopy2DByteSlice(input [][]byte) [][]byte {
|
||||
if input == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
dst := make([][]byte, len(input))
|
||||
for i, r := range input {
|
||||
tmp := make([]byte, len(r))
|
||||
copy(tmp, r)
|
||||
dst[i] = tmp
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
func (b *BeaconState) safeCopyBytesAtIndex(input [][]byte, idx uint64) ([]byte, error) {
|
||||
if input == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if uint64(len(input)) <= idx {
|
||||
return nil, fmt.Errorf("index %d out of range", idx)
|
||||
}
|
||||
root := make([]byte, 32)
|
||||
copy(root, input[idx])
|
||||
return root, nil
|
||||
}
|
||||
|
||||
func (b *BeaconState) safeCopyPendingAttestationSlice(input []*pbp2p.PendingAttestation) []*pbp2p.PendingAttestation {
|
||||
if input == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
res := make([]*pbp2p.PendingAttestation, len(input))
|
||||
for i := 0; i < len(res); i++ {
|
||||
res[i] = CopyPendingAttestation(input[i])
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (b *BeaconState) safeCopyCheckpoint(input *ethpb.Checkpoint) *ethpb.Checkpoint {
|
||||
if input == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return CopyCheckpoint(input)
|
||||
}
|
||||
345
beacon-chain/state/stateV0/getters_validator.go
Normal file
345
beacon-chain/state/stateV0/getters_validator.go
Normal file
@@ -0,0 +1,345 @@
|
||||
package stateV0
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/hashutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/htrutils"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
)
|
||||
|
||||
// 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] = 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) {
|
||||
return nil, fmt.Errorf("index %d out of range", idx)
|
||||
}
|
||||
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
val := b.state.Validators[idx]
|
||||
return 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) (iface.ReadOnlyValidator, error) {
|
||||
if !b.hasInnerState() {
|
||||
return ReadOnlyValidator{}, ErrNilInnerState
|
||||
}
|
||||
if b.state.Validators == nil {
|
||||
return ReadOnlyValidator{}, nil
|
||||
}
|
||||
if uint64(len(b.state.Validators)) <= uint64(idx) {
|
||||
return ReadOnlyValidator{}, fmt.Errorf("index %d out of range", idx)
|
||||
}
|
||||
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
return ReadOnlyValidator{b.state.Validators[idx]}, nil
|
||||
}
|
||||
|
||||
// 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()
|
||||
idx, ok := b.valMapHandler.Get(key)
|
||||
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 iface.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 {
|
||||
err := f(i, ReadOnlyValidator{validator: v})
|
||||
if 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
|
||||
}
|
||||
|
||||
func (h *stateRootHasher) validatorRegistryRoot(validators []*ethpb.Validator) ([32]byte, error) {
|
||||
hashKeyElements := make([]byte, len(validators)*32)
|
||||
roots := make([][32]byte, len(validators))
|
||||
emptyKey := hashutil.FastSum256(hashKeyElements)
|
||||
hasher := hashutil.CustomSHA256Hasher()
|
||||
bytesProcessed := 0
|
||||
for i := 0; i < len(validators); i++ {
|
||||
val, err := h.validatorRoot(hasher, validators[i])
|
||||
if err != nil {
|
||||
return [32]byte{}, errors.Wrap(err, "could not compute validators merkleization")
|
||||
}
|
||||
copy(hashKeyElements[bytesProcessed:bytesProcessed+32], val[:])
|
||||
roots[i] = val
|
||||
bytesProcessed += 32
|
||||
}
|
||||
|
||||
hashKey := hashutil.FastSum256(hashKeyElements)
|
||||
if hashKey != emptyKey && h.rootsCache != nil {
|
||||
if found, ok := h.rootsCache.Get(string(hashKey[:])); found != nil && ok {
|
||||
return found.([32]byte), nil
|
||||
}
|
||||
}
|
||||
|
||||
validatorsRootsRoot, err := htrutils.BitwiseMerkleizeArrays(hasher, roots, uint64(len(roots)), params.BeaconConfig().ValidatorRegistryLimit)
|
||||
if err != nil {
|
||||
return [32]byte{}, errors.Wrap(err, "could not compute validator registry merkleization")
|
||||
}
|
||||
validatorsRootsBuf := new(bytes.Buffer)
|
||||
if err := binary.Write(validatorsRootsBuf, binary.LittleEndian, uint64(len(validators))); err != nil {
|
||||
return [32]byte{}, errors.Wrap(err, "could not marshal validator registry length")
|
||||
}
|
||||
// We need to mix in the length of the slice.
|
||||
var validatorsRootsBufRoot [32]byte
|
||||
copy(validatorsRootsBufRoot[:], validatorsRootsBuf.Bytes())
|
||||
res := htrutils.MixInLength(validatorsRootsRoot, validatorsRootsBufRoot[:])
|
||||
if hashKey != emptyKey && h.rootsCache != nil {
|
||||
h.rootsCache.Set(string(hashKey[:]), res, 32)
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (h *stateRootHasher) validatorRoot(hasher htrutils.HashFn, validator *ethpb.Validator) ([32]byte, error) {
|
||||
if validator == nil {
|
||||
return [32]byte{}, errors.New("nil validator")
|
||||
}
|
||||
|
||||
enc := stateutil.ValidatorEncKey(validator)
|
||||
// Check if it exists in cache:
|
||||
if h.rootsCache != nil {
|
||||
if found, ok := h.rootsCache.Get(string(enc)); found != nil && ok {
|
||||
return found.([32]byte), nil
|
||||
}
|
||||
}
|
||||
|
||||
valRoot, err := stateutil.ValidatorRootWithHasher(hasher, validator)
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
|
||||
if h.rootsCache != nil {
|
||||
h.rootsCache.Set(string(enc), valRoot, 32)
|
||||
}
|
||||
return valRoot, nil
|
||||
}
|
||||
|
||||
// ValidatorRegistryRoot computes the HashTreeRoot Merkleization of
|
||||
// a list of validator structs according to the eth2
|
||||
// Simple Serialize specification.
|
||||
func ValidatorRegistryRoot(vals []*ethpb.Validator) ([32]byte, error) {
|
||||
if featureconfig.Get().EnableSSZCache {
|
||||
return cachedHasher.validatorRegistryRoot(vals)
|
||||
}
|
||||
return nocachedHasher.validatorRegistryRoot(vals)
|
||||
}
|
||||
@@ -1,754 +0,0 @@
|
||||
package stateV0
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"github.com/pkg/errors"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/go-bitfield"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/hashutil"
|
||||
)
|
||||
|
||||
// For our setters, we have a field reference counter through
|
||||
// which we can track shared field references. This helps when
|
||||
// performing state copies, as we simply copy the reference to the
|
||||
// field. When we do need to do need to modify these fields, we
|
||||
// perform a full copy of the field. This is true of most of our
|
||||
// fields except for the following below.
|
||||
// 1) BlockRoots
|
||||
// 2) StateRoots
|
||||
// 3) Eth1DataVotes
|
||||
// 4) RandaoMixes
|
||||
// 5) HistoricalRoots
|
||||
// 6) CurrentEpochAttestations
|
||||
// 7) PreviousEpochAttestations
|
||||
//
|
||||
// The fields referred to above are instead copied by reference, where
|
||||
// we simply copy the reference to the underlying object instead of the
|
||||
// whole object. This is possible due to how we have structured our state
|
||||
// as we copy the value on read, so as to ensure the underlying object is
|
||||
// not mutated while it is being accessed during a state read.
|
||||
|
||||
// SetGenesisTime for the beacon state.
|
||||
func (b *BeaconState) SetGenesisTime(val uint64) error {
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.state.GenesisTime = val
|
||||
b.markFieldAsDirty(genesisTime)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetGenesisValidatorRoot for the beacon state.
|
||||
func (b *BeaconState) SetGenesisValidatorRoot(val []byte) error {
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.state.GenesisValidatorsRoot = val
|
||||
b.markFieldAsDirty(genesisValidatorRoot)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetSlot for the beacon state.
|
||||
func (b *BeaconState) SetSlot(val types.Slot) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.state.Slot = val
|
||||
b.markFieldAsDirty(slot)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetFork version for the beacon chain.
|
||||
func (b *BeaconState) SetFork(val *pbp2p.Fork) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
fk, ok := proto.Clone(val).(*pbp2p.Fork)
|
||||
if !ok {
|
||||
return errors.New("proto.Clone did not return a fork proto")
|
||||
}
|
||||
b.state.Fork = fk
|
||||
b.markFieldAsDirty(fork)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetLatestBlockHeader in the beacon state.
|
||||
func (b *BeaconState) SetLatestBlockHeader(val *ethpb.BeaconBlockHeader) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.state.LatestBlockHeader = CopyBeaconBlockHeader(val)
|
||||
b.markFieldAsDirty(latestBlockHeader)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetBlockRoots for the beacon state. Updates the entire
|
||||
// list to a new value by overwriting the previous one.
|
||||
func (b *BeaconState) SetBlockRoots(val [][]byte) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.sharedFieldReferences[blockRoots].MinusRef()
|
||||
b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1)
|
||||
|
||||
b.state.BlockRoots = val
|
||||
b.markFieldAsDirty(blockRoots)
|
||||
b.rebuildTrie[blockRoots] = true
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateBlockRootAtIndex for the beacon state. Updates the block root
|
||||
// at a specific index to a new value.
|
||||
func (b *BeaconState) UpdateBlockRootAtIndex(idx uint64, blockRoot [32]byte) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
if uint64(len(b.state.BlockRoots)) <= idx {
|
||||
return fmt.Errorf("invalid index provided %d", idx)
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
r := b.state.BlockRoots
|
||||
if ref := b.sharedFieldReferences[blockRoots]; ref.Refs() > 1 {
|
||||
// Copy elements in underlying array by reference.
|
||||
r = make([][]byte, len(b.state.BlockRoots))
|
||||
copy(r, b.state.BlockRoots)
|
||||
ref.MinusRef()
|
||||
b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1)
|
||||
}
|
||||
|
||||
r[idx] = blockRoot[:]
|
||||
b.state.BlockRoots = r
|
||||
|
||||
b.markFieldAsDirty(blockRoots)
|
||||
b.addDirtyIndices(blockRoots, []uint64{idx})
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetStateRoots for the beacon state. Updates the state roots
|
||||
// to a new value by overwriting the previous value.
|
||||
func (b *BeaconState) SetStateRoots(val [][]byte) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.sharedFieldReferences[stateRoots].MinusRef()
|
||||
b.sharedFieldReferences[stateRoots] = stateutil.NewRef(1)
|
||||
|
||||
b.state.StateRoots = val
|
||||
b.markFieldAsDirty(stateRoots)
|
||||
b.rebuildTrie[stateRoots] = true
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateStateRootAtIndex for the beacon state. Updates the state root
|
||||
// at a specific index to a new value.
|
||||
func (b *BeaconState) UpdateStateRootAtIndex(idx uint64, stateRoot [32]byte) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
|
||||
b.lock.RLock()
|
||||
if uint64(len(b.state.StateRoots)) <= idx {
|
||||
b.lock.RUnlock()
|
||||
return errors.Errorf("invalid index provided %d", idx)
|
||||
}
|
||||
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.state.StateRoots
|
||||
if ref := b.sharedFieldReferences[stateRoots]; ref.Refs() > 1 {
|
||||
// Copy elements in underlying array by reference.
|
||||
r = make([][]byte, len(b.state.StateRoots))
|
||||
copy(r, b.state.StateRoots)
|
||||
ref.MinusRef()
|
||||
b.sharedFieldReferences[stateRoots] = stateutil.NewRef(1)
|
||||
}
|
||||
|
||||
r[idx] = stateRoot[:]
|
||||
b.state.StateRoots = r
|
||||
|
||||
b.markFieldAsDirty(stateRoots)
|
||||
b.addDirtyIndices(stateRoots, []uint64{idx})
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetHistoricalRoots for the beacon state. Updates the entire
|
||||
// list to a new value by overwriting the previous one.
|
||||
func (b *BeaconState) SetHistoricalRoots(val [][]byte) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.sharedFieldReferences[historicalRoots].MinusRef()
|
||||
b.sharedFieldReferences[historicalRoots] = stateutil.NewRef(1)
|
||||
|
||||
b.state.HistoricalRoots = val
|
||||
b.markFieldAsDirty(historicalRoots)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetEth1Data for the beacon state.
|
||||
func (b *BeaconState) SetEth1Data(val *ethpb.Eth1Data) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.state.Eth1Data = val
|
||||
b.markFieldAsDirty(eth1Data)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetEth1DataVotes for the beacon state. Updates the entire
|
||||
// list to a new value by overwriting the previous one.
|
||||
func (b *BeaconState) SetEth1DataVotes(val []*ethpb.Eth1Data) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.sharedFieldReferences[eth1DataVotes].MinusRef()
|
||||
b.sharedFieldReferences[eth1DataVotes] = stateutil.NewRef(1)
|
||||
|
||||
b.state.Eth1DataVotes = val
|
||||
b.markFieldAsDirty(eth1DataVotes)
|
||||
b.rebuildTrie[eth1DataVotes] = true
|
||||
return nil
|
||||
}
|
||||
|
||||
// AppendEth1DataVotes for the beacon state. Appends the new value
|
||||
// to the the end of list.
|
||||
func (b *BeaconState) AppendEth1DataVotes(val *ethpb.Eth1Data) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
votes := b.state.Eth1DataVotes
|
||||
if b.sharedFieldReferences[eth1DataVotes].Refs() > 1 {
|
||||
// Copy elements in underlying array by reference.
|
||||
votes = make([]*ethpb.Eth1Data, len(b.state.Eth1DataVotes))
|
||||
copy(votes, b.state.Eth1DataVotes)
|
||||
b.sharedFieldReferences[eth1DataVotes].MinusRef()
|
||||
b.sharedFieldReferences[eth1DataVotes] = stateutil.NewRef(1)
|
||||
}
|
||||
|
||||
b.state.Eth1DataVotes = append(votes, val)
|
||||
b.markFieldAsDirty(eth1DataVotes)
|
||||
b.addDirtyIndices(eth1DataVotes, []uint64{uint64(len(b.state.Eth1DataVotes) - 1)})
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetEth1DepositIndex for the beacon state.
|
||||
func (b *BeaconState) SetEth1DepositIndex(val uint64) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.state.Eth1DepositIndex = val
|
||||
b.markFieldAsDirty(eth1DepositIndex)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetValidators for the beacon state. Updates the entire
|
||||
// to a new value by overwriting the previous one.
|
||||
func (b *BeaconState) SetValidators(val []*ethpb.Validator) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.state.Validators = val
|
||||
b.sharedFieldReferences[validators].MinusRef()
|
||||
b.sharedFieldReferences[validators] = stateutil.NewRef(1)
|
||||
b.markFieldAsDirty(validators)
|
||||
b.rebuildTrie[validators] = true
|
||||
b.valMapHandler = stateutil.NewValMapHandler(b.state.Validators)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ApplyToEveryValidator applies the provided callback function to each validator in the
|
||||
// validator registry.
|
||||
func (b *BeaconState) ApplyToEveryValidator(f func(idx int, val *ethpb.Validator) (bool, *ethpb.Validator, error)) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
v := b.state.Validators
|
||||
if ref := b.sharedFieldReferences[validators]; ref.Refs() > 1 {
|
||||
v = b.validatorsReferences()
|
||||
ref.MinusRef()
|
||||
b.sharedFieldReferences[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 changed {
|
||||
changedVals = append(changedVals, uint64(i))
|
||||
v[i] = newVal
|
||||
}
|
||||
}
|
||||
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.state.Validators = v
|
||||
b.markFieldAsDirty(validators)
|
||||
b.addDirtyIndices(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 types.ValidatorIndex, val *ethpb.Validator) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
if uint64(len(b.state.Validators)) <= uint64(idx) {
|
||||
return errors.Errorf("invalid index provided %d", idx)
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
v := b.state.Validators
|
||||
if ref := b.sharedFieldReferences[validators]; ref.Refs() > 1 {
|
||||
v = b.validatorsReferences()
|
||||
ref.MinusRef()
|
||||
b.sharedFieldReferences[validators] = stateutil.NewRef(1)
|
||||
}
|
||||
|
||||
v[idx] = val
|
||||
b.state.Validators = v
|
||||
b.markFieldAsDirty(validators)
|
||||
b.addDirtyIndices(validators, []uint64{uint64(idx)})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetBalances for the beacon state. Updates the entire
|
||||
// list to a new value by overwriting the previous one.
|
||||
func (b *BeaconState) SetBalances(val []uint64) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.sharedFieldReferences[balances].MinusRef()
|
||||
b.sharedFieldReferences[balances] = stateutil.NewRef(1)
|
||||
|
||||
b.state.Balances = val
|
||||
b.markFieldAsDirty(balances)
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateBalancesAtIndex for the beacon state. This method updates the balance
|
||||
// at a specific index to a new value.
|
||||
func (b *BeaconState) UpdateBalancesAtIndex(idx types.ValidatorIndex, val uint64) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
if uint64(len(b.state.Balances)) <= uint64(idx) {
|
||||
return errors.Errorf("invalid index provided %d", idx)
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
bals := b.state.Balances
|
||||
if b.sharedFieldReferences[balances].Refs() > 1 {
|
||||
bals = b.balances()
|
||||
b.sharedFieldReferences[balances].MinusRef()
|
||||
b.sharedFieldReferences[balances] = stateutil.NewRef(1)
|
||||
}
|
||||
|
||||
bals[idx] = val
|
||||
b.state.Balances = bals
|
||||
b.markFieldAsDirty(balances)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetRandaoMixes for the beacon state. Updates the entire
|
||||
// randao mixes to a new value by overwriting the previous one.
|
||||
func (b *BeaconState) SetRandaoMixes(val [][]byte) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.sharedFieldReferences[randaoMixes].MinusRef()
|
||||
b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1)
|
||||
|
||||
b.state.RandaoMixes = val
|
||||
b.markFieldAsDirty(randaoMixes)
|
||||
b.rebuildTrie[randaoMixes] = true
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateRandaoMixesAtIndex for the beacon state. Updates the randao mixes
|
||||
// at a specific index to a new value.
|
||||
func (b *BeaconState) UpdateRandaoMixesAtIndex(idx uint64, val []byte) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
if uint64(len(b.state.RandaoMixes)) <= idx {
|
||||
return errors.Errorf("invalid index provided %d", idx)
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
mixes := b.state.RandaoMixes
|
||||
if refs := b.sharedFieldReferences[randaoMixes].Refs(); refs > 1 {
|
||||
// Copy elements in underlying array by reference.
|
||||
mixes = make([][]byte, len(b.state.RandaoMixes))
|
||||
copy(mixes, b.state.RandaoMixes)
|
||||
b.sharedFieldReferences[randaoMixes].MinusRef()
|
||||
b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1)
|
||||
}
|
||||
|
||||
mixes[idx] = val
|
||||
b.state.RandaoMixes = mixes
|
||||
b.markFieldAsDirty(randaoMixes)
|
||||
b.addDirtyIndices(randaoMixes, []uint64{idx})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetSlashings for the beacon state. Updates the entire
|
||||
// list to a new value by overwriting the previous one.
|
||||
func (b *BeaconState) SetSlashings(val []uint64) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.sharedFieldReferences[slashings].MinusRef()
|
||||
b.sharedFieldReferences[slashings] = stateutil.NewRef(1)
|
||||
|
||||
b.state.Slashings = val
|
||||
b.markFieldAsDirty(slashings)
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateSlashingsAtIndex for the beacon state. Updates the slashings
|
||||
// at a specific index to a new value.
|
||||
func (b *BeaconState) UpdateSlashingsAtIndex(idx, val uint64) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
if uint64(len(b.state.Slashings)) <= idx {
|
||||
return errors.Errorf("invalid index provided %d", idx)
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
s := b.state.Slashings
|
||||
if b.sharedFieldReferences[slashings].Refs() > 1 {
|
||||
s = b.slashings()
|
||||
b.sharedFieldReferences[slashings].MinusRef()
|
||||
b.sharedFieldReferences[slashings] = stateutil.NewRef(1)
|
||||
}
|
||||
|
||||
s[idx] = val
|
||||
|
||||
b.state.Slashings = s
|
||||
|
||||
b.markFieldAsDirty(slashings)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *BeaconState) setPreviousEpochAttestations(val []*pbp2p.PendingAttestation) {
|
||||
b.sharedFieldReferences[previousEpochAttestations].MinusRef()
|
||||
b.sharedFieldReferences[previousEpochAttestations] = stateutil.NewRef(1)
|
||||
|
||||
b.state.PreviousEpochAttestations = val
|
||||
b.markFieldAsDirty(previousEpochAttestations)
|
||||
b.rebuildTrie[previousEpochAttestations] = true
|
||||
}
|
||||
|
||||
func (b *BeaconState) setCurrentEpochAttestations(val []*pbp2p.PendingAttestation) {
|
||||
b.sharedFieldReferences[currentEpochAttestations].MinusRef()
|
||||
b.sharedFieldReferences[currentEpochAttestations] = stateutil.NewRef(1)
|
||||
|
||||
b.state.CurrentEpochAttestations = val
|
||||
b.markFieldAsDirty(currentEpochAttestations)
|
||||
b.rebuildTrie[currentEpochAttestations] = true
|
||||
}
|
||||
|
||||
// RotateAttestations sets the previous epoch attestations to the current epoch attestations and
|
||||
// then clears the current epoch attestations.
|
||||
func (b *BeaconState) RotateAttestations() error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.setPreviousEpochAttestations(b.currentEpochAttestations())
|
||||
b.setCurrentEpochAttestations([]*pbp2p.PendingAttestation{})
|
||||
return nil
|
||||
}
|
||||
|
||||
// AppendHistoricalRoots for the beacon state. Appends the new value
|
||||
// to the the end of list.
|
||||
func (b *BeaconState) AppendHistoricalRoots(root [32]byte) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
roots := b.state.HistoricalRoots
|
||||
if b.sharedFieldReferences[historicalRoots].Refs() > 1 {
|
||||
roots = make([][]byte, len(b.state.HistoricalRoots))
|
||||
copy(roots, b.state.HistoricalRoots)
|
||||
b.sharedFieldReferences[historicalRoots].MinusRef()
|
||||
b.sharedFieldReferences[historicalRoots] = stateutil.NewRef(1)
|
||||
}
|
||||
|
||||
b.state.HistoricalRoots = append(roots, root[:])
|
||||
b.markFieldAsDirty(historicalRoots)
|
||||
return nil
|
||||
}
|
||||
|
||||
// AppendCurrentEpochAttestations for the beacon state. Appends the new value
|
||||
// to the the end of list.
|
||||
func (b *BeaconState) AppendCurrentEpochAttestations(val *pbp2p.PendingAttestation) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
atts := b.state.CurrentEpochAttestations
|
||||
if b.sharedFieldReferences[currentEpochAttestations].Refs() > 1 {
|
||||
// Copy elements in underlying array by reference.
|
||||
atts = make([]*pbp2p.PendingAttestation, len(b.state.CurrentEpochAttestations))
|
||||
copy(atts, b.state.CurrentEpochAttestations)
|
||||
b.sharedFieldReferences[currentEpochAttestations].MinusRef()
|
||||
b.sharedFieldReferences[currentEpochAttestations] = stateutil.NewRef(1)
|
||||
}
|
||||
|
||||
b.state.CurrentEpochAttestations = append(atts, val)
|
||||
b.markFieldAsDirty(currentEpochAttestations)
|
||||
b.dirtyIndices[currentEpochAttestations] = append(b.dirtyIndices[currentEpochAttestations], uint64(len(b.state.CurrentEpochAttestations)-1))
|
||||
return nil
|
||||
}
|
||||
|
||||
// AppendPreviousEpochAttestations for the beacon state. Appends the new value
|
||||
// to the the end of list.
|
||||
func (b *BeaconState) AppendPreviousEpochAttestations(val *pbp2p.PendingAttestation) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
atts := b.state.PreviousEpochAttestations
|
||||
if b.sharedFieldReferences[previousEpochAttestations].Refs() > 1 {
|
||||
atts = make([]*pbp2p.PendingAttestation, len(b.state.PreviousEpochAttestations))
|
||||
copy(atts, b.state.PreviousEpochAttestations)
|
||||
b.sharedFieldReferences[previousEpochAttestations].MinusRef()
|
||||
b.sharedFieldReferences[previousEpochAttestations] = stateutil.NewRef(1)
|
||||
}
|
||||
|
||||
b.state.PreviousEpochAttestations = append(atts, val)
|
||||
b.markFieldAsDirty(previousEpochAttestations)
|
||||
b.addDirtyIndices(previousEpochAttestations, []uint64{uint64(len(b.state.PreviousEpochAttestations) - 1)})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// AppendValidator for the beacon state. Appends the new value
|
||||
// to the the end of list.
|
||||
func (b *BeaconState) AppendValidator(val *ethpb.Validator) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
vals := b.state.Validators
|
||||
if b.sharedFieldReferences[validators].Refs() > 1 {
|
||||
vals = b.validatorsReferences()
|
||||
b.sharedFieldReferences[validators].MinusRef()
|
||||
b.sharedFieldReferences[validators] = stateutil.NewRef(1)
|
||||
}
|
||||
|
||||
// append validator to slice
|
||||
b.state.Validators = append(vals, val)
|
||||
valIdx := types.ValidatorIndex(len(b.state.Validators) - 1)
|
||||
|
||||
// Copy if this is a shared validator map
|
||||
if ref := b.valMapHandler.MapRef(); ref.Refs() > 1 {
|
||||
valMap := b.valMapHandler.Copy()
|
||||
ref.MinusRef()
|
||||
b.valMapHandler = valMap
|
||||
}
|
||||
b.valMapHandler.Set(bytesutil.ToBytes48(val.PublicKey), valIdx)
|
||||
|
||||
b.markFieldAsDirty(validators)
|
||||
b.addDirtyIndices(validators, []uint64{uint64(valIdx)})
|
||||
return nil
|
||||
}
|
||||
|
||||
// AppendBalance for the beacon state. Appends the new value
|
||||
// to the the end of list.
|
||||
func (b *BeaconState) AppendBalance(bal uint64) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
bals := b.state.Balances
|
||||
if b.sharedFieldReferences[balances].Refs() > 1 {
|
||||
bals = b.balances()
|
||||
b.sharedFieldReferences[balances].MinusRef()
|
||||
b.sharedFieldReferences[balances] = stateutil.NewRef(1)
|
||||
}
|
||||
|
||||
b.state.Balances = append(bals, bal)
|
||||
b.markFieldAsDirty(balances)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetJustificationBits for the beacon state.
|
||||
func (b *BeaconState) SetJustificationBits(val bitfield.Bitvector4) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.state.JustificationBits = val
|
||||
b.markFieldAsDirty(justificationBits)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetPreviousJustifiedCheckpoint for the beacon state.
|
||||
func (b *BeaconState) SetPreviousJustifiedCheckpoint(val *ethpb.Checkpoint) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.state.PreviousJustifiedCheckpoint = val
|
||||
b.markFieldAsDirty(previousJustifiedCheckpoint)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetCurrentJustifiedCheckpoint for the beacon state.
|
||||
func (b *BeaconState) SetCurrentJustifiedCheckpoint(val *ethpb.Checkpoint) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.state.CurrentJustifiedCheckpoint = val
|
||||
b.markFieldAsDirty(currentJustifiedCheckpoint)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetFinalizedCheckpoint for the beacon state.
|
||||
func (b *BeaconState) SetFinalizedCheckpoint(val *ethpb.Checkpoint) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.state.FinalizedCheckpoint = val
|
||||
b.markFieldAsDirty(finalizedCheckpoint)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Recomputes the branch up the index in the Merkle trie representation
|
||||
// of the beacon state. This method performs map reads and the caller MUST
|
||||
// hold the lock before calling this method.
|
||||
func (b *BeaconState) recomputeRoot(idx int) {
|
||||
hashFunc := hashutil.CustomSHA256Hasher()
|
||||
layers := b.merkleLayers
|
||||
// The merkle tree structure looks as follows:
|
||||
// [[r1, r2, r3, r4], [parent1, parent2], [root]]
|
||||
// Using information about the index which changed, idx, we recompute
|
||||
// only its branch up the tree.
|
||||
currentIndex := idx
|
||||
root := b.merkleLayers[0][idx]
|
||||
for i := 0; i < len(layers)-1; i++ {
|
||||
isLeft := currentIndex%2 == 0
|
||||
neighborIdx := currentIndex ^ 1
|
||||
|
||||
neighbor := make([]byte, 32)
|
||||
if layers[i] != nil && len(layers[i]) != 0 && neighborIdx < len(layers[i]) {
|
||||
neighbor = layers[i][neighborIdx]
|
||||
}
|
||||
if isLeft {
|
||||
parentHash := hashFunc(append(root, neighbor...))
|
||||
root = parentHash[:]
|
||||
} else {
|
||||
parentHash := hashFunc(append(neighbor, root...))
|
||||
root = parentHash[:]
|
||||
}
|
||||
parentIdx := currentIndex / 2
|
||||
// Update the cached layers at the parent index.
|
||||
layers[i+1][parentIdx] = root
|
||||
currentIndex = parentIdx
|
||||
}
|
||||
b.merkleLayers = layers
|
||||
}
|
||||
|
||||
func (b *BeaconState) markFieldAsDirty(field fieldIndex) {
|
||||
_, ok := b.dirtyFields[field]
|
||||
if !ok {
|
||||
b.dirtyFields[field] = true
|
||||
}
|
||||
// do nothing if field already exists
|
||||
}
|
||||
|
||||
// addDirtyIndices adds the relevant dirty field indices, so that they
|
||||
// can be recomputed.
|
||||
func (b *BeaconState) addDirtyIndices(index fieldIndex, indices []uint64) {
|
||||
b.dirtyIndices[index] = append(b.dirtyIndices[index], indices...)
|
||||
}
|
||||
99
beacon-chain/state/stateV0/setters_attestation.go
Normal file
99
beacon-chain/state/stateV0/setters_attestation.go
Normal file
@@ -0,0 +1,99 @@
|
||||
package stateV0
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
)
|
||||
|
||||
// RotateAttestations sets the previous epoch attestations to the current epoch attestations and
|
||||
// then clears the current epoch attestations.
|
||||
func (b *BeaconState) RotateAttestations() error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.setPreviousEpochAttestations(b.currentEpochAttestations())
|
||||
b.setCurrentEpochAttestations([]*pbp2p.PendingAttestation{})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *BeaconState) setPreviousEpochAttestations(val []*pbp2p.PendingAttestation) {
|
||||
b.sharedFieldReferences[previousEpochAttestations].MinusRef()
|
||||
b.sharedFieldReferences[previousEpochAttestations] = stateutil.NewRef(1)
|
||||
|
||||
b.state.PreviousEpochAttestations = val
|
||||
b.markFieldAsDirty(previousEpochAttestations)
|
||||
b.rebuildTrie[previousEpochAttestations] = true
|
||||
}
|
||||
|
||||
func (b *BeaconState) setCurrentEpochAttestations(val []*pbp2p.PendingAttestation) {
|
||||
b.sharedFieldReferences[currentEpochAttestations].MinusRef()
|
||||
b.sharedFieldReferences[currentEpochAttestations] = stateutil.NewRef(1)
|
||||
|
||||
b.state.CurrentEpochAttestations = val
|
||||
b.markFieldAsDirty(currentEpochAttestations)
|
||||
b.rebuildTrie[currentEpochAttestations] = true
|
||||
}
|
||||
|
||||
// AppendCurrentEpochAttestations for the beacon state. Appends the new value
|
||||
// to the the end of list.
|
||||
func (b *BeaconState) AppendCurrentEpochAttestations(val *pbp2p.PendingAttestation) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
atts := b.state.CurrentEpochAttestations
|
||||
max := uint64(params.BeaconConfig().SlotsPerEpoch) * params.BeaconConfig().MaxAttestations
|
||||
if uint64(len(atts)) >= max {
|
||||
return fmt.Errorf("current pending attestation exceeds max length %d", max)
|
||||
}
|
||||
|
||||
if b.sharedFieldReferences[currentEpochAttestations].Refs() > 1 {
|
||||
// Copy elements in underlying array by reference.
|
||||
atts = make([]*pbp2p.PendingAttestation, len(b.state.CurrentEpochAttestations))
|
||||
copy(atts, b.state.CurrentEpochAttestations)
|
||||
b.sharedFieldReferences[currentEpochAttestations].MinusRef()
|
||||
b.sharedFieldReferences[currentEpochAttestations] = stateutil.NewRef(1)
|
||||
}
|
||||
|
||||
b.state.CurrentEpochAttestations = append(atts, val)
|
||||
b.markFieldAsDirty(currentEpochAttestations)
|
||||
b.dirtyIndices[currentEpochAttestations] = append(b.dirtyIndices[currentEpochAttestations], uint64(len(b.state.CurrentEpochAttestations)-1))
|
||||
return nil
|
||||
}
|
||||
|
||||
// AppendPreviousEpochAttestations for the beacon state. Appends the new value
|
||||
// to the the end of list.
|
||||
func (b *BeaconState) AppendPreviousEpochAttestations(val *pbp2p.PendingAttestation) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
atts := b.state.PreviousEpochAttestations
|
||||
max := uint64(params.BeaconConfig().SlotsPerEpoch) * params.BeaconConfig().MaxAttestations
|
||||
if uint64(len(atts)) >= max {
|
||||
return fmt.Errorf("previous pending attestation exceeds max length %d", max)
|
||||
}
|
||||
|
||||
if b.sharedFieldReferences[previousEpochAttestations].Refs() > 1 {
|
||||
atts = make([]*pbp2p.PendingAttestation, len(b.state.PreviousEpochAttestations))
|
||||
copy(atts, b.state.PreviousEpochAttestations)
|
||||
b.sharedFieldReferences[previousEpochAttestations].MinusRef()
|
||||
b.sharedFieldReferences[previousEpochAttestations] = stateutil.NewRef(1)
|
||||
}
|
||||
|
||||
b.state.PreviousEpochAttestations = append(atts, val)
|
||||
b.markFieldAsDirty(previousEpochAttestations)
|
||||
b.addDirtyIndices(previousEpochAttestations, []uint64{uint64(len(b.state.PreviousEpochAttestations) - 1)})
|
||||
|
||||
return nil
|
||||
}
|
||||
68
beacon-chain/state/stateV0/setters_block.go
Normal file
68
beacon-chain/state/stateV0/setters_block.go
Normal file
@@ -0,0 +1,68 @@
|
||||
package stateV0
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
)
|
||||
|
||||
// SetLatestBlockHeader in the beacon state.
|
||||
func (b *BeaconState) SetLatestBlockHeader(val *ethpb.BeaconBlockHeader) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.state.LatestBlockHeader = CopyBeaconBlockHeader(val)
|
||||
b.markFieldAsDirty(latestBlockHeader)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetBlockRoots for the beacon state. Updates the entire
|
||||
// list to a new value by overwriting the previous one.
|
||||
func (b *BeaconState) SetBlockRoots(val [][]byte) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.sharedFieldReferences[blockRoots].MinusRef()
|
||||
b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1)
|
||||
|
||||
b.state.BlockRoots = val
|
||||
b.markFieldAsDirty(blockRoots)
|
||||
b.rebuildTrie[blockRoots] = true
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateBlockRootAtIndex for the beacon state. Updates the block root
|
||||
// at a specific index to a new value.
|
||||
func (b *BeaconState) UpdateBlockRootAtIndex(idx uint64, blockRoot [32]byte) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
if uint64(len(b.state.BlockRoots)) <= idx {
|
||||
return fmt.Errorf("invalid index provided %d", idx)
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
r := b.state.BlockRoots
|
||||
if ref := b.sharedFieldReferences[blockRoots]; ref.Refs() > 1 {
|
||||
// Copy elements in underlying array by reference.
|
||||
r = make([][]byte, len(b.state.BlockRoots))
|
||||
copy(r, b.state.BlockRoots)
|
||||
ref.MinusRef()
|
||||
b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1)
|
||||
}
|
||||
|
||||
r[idx] = blockRoot[:]
|
||||
b.state.BlockRoots = r
|
||||
|
||||
b.markFieldAsDirty(blockRoots)
|
||||
b.addDirtyIndices(blockRoots, []uint64{idx})
|
||||
return nil
|
||||
}
|
||||
58
beacon-chain/state/stateV0/setters_checkpoint.go
Normal file
58
beacon-chain/state/stateV0/setters_checkpoint.go
Normal file
@@ -0,0 +1,58 @@
|
||||
package stateV0
|
||||
|
||||
import (
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/go-bitfield"
|
||||
)
|
||||
|
||||
// SetJustificationBits for the beacon state.
|
||||
func (b *BeaconState) SetJustificationBits(val bitfield.Bitvector4) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.state.JustificationBits = val
|
||||
b.markFieldAsDirty(justificationBits)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetPreviousJustifiedCheckpoint for the beacon state.
|
||||
func (b *BeaconState) SetPreviousJustifiedCheckpoint(val *ethpb.Checkpoint) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.state.PreviousJustifiedCheckpoint = val
|
||||
b.markFieldAsDirty(previousJustifiedCheckpoint)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetCurrentJustifiedCheckpoint for the beacon state.
|
||||
func (b *BeaconState) SetCurrentJustifiedCheckpoint(val *ethpb.Checkpoint) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.state.CurrentJustifiedCheckpoint = val
|
||||
b.markFieldAsDirty(currentJustifiedCheckpoint)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetFinalizedCheckpoint for the beacon state.
|
||||
func (b *BeaconState) SetFinalizedCheckpoint(val *ethpb.Checkpoint) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.state.FinalizedCheckpoint = val
|
||||
b.markFieldAsDirty(finalizedCheckpoint)
|
||||
return nil
|
||||
}
|
||||
74
beacon-chain/state/stateV0/setters_eth1.go
Normal file
74
beacon-chain/state/stateV0/setters_eth1.go
Normal file
@@ -0,0 +1,74 @@
|
||||
package stateV0
|
||||
|
||||
import (
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
)
|
||||
|
||||
// SetEth1Data for the beacon state.
|
||||
func (b *BeaconState) SetEth1Data(val *ethpb.Eth1Data) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.state.Eth1Data = val
|
||||
b.markFieldAsDirty(eth1Data)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetEth1DataVotes for the beacon state. Updates the entire
|
||||
// list to a new value by overwriting the previous one.
|
||||
func (b *BeaconState) SetEth1DataVotes(val []*ethpb.Eth1Data) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.sharedFieldReferences[eth1DataVotes].MinusRef()
|
||||
b.sharedFieldReferences[eth1DataVotes] = stateutil.NewRef(1)
|
||||
|
||||
b.state.Eth1DataVotes = val
|
||||
b.markFieldAsDirty(eth1DataVotes)
|
||||
b.rebuildTrie[eth1DataVotes] = true
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetEth1DepositIndex for the beacon state.
|
||||
func (b *BeaconState) SetEth1DepositIndex(val uint64) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.state.Eth1DepositIndex = val
|
||||
b.markFieldAsDirty(eth1DepositIndex)
|
||||
return nil
|
||||
}
|
||||
|
||||
// AppendEth1DataVotes for the beacon state. Appends the new value
|
||||
// to the the end of list.
|
||||
func (b *BeaconState) AppendEth1DataVotes(val *ethpb.Eth1Data) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
votes := b.state.Eth1DataVotes
|
||||
if b.sharedFieldReferences[eth1DataVotes].Refs() > 1 {
|
||||
// Copy elements in underlying array by reference.
|
||||
votes = make([]*ethpb.Eth1Data, len(b.state.Eth1DataVotes))
|
||||
copy(votes, b.state.Eth1DataVotes)
|
||||
b.sharedFieldReferences[eth1DataVotes].MinusRef()
|
||||
b.sharedFieldReferences[eth1DataVotes] = stateutil.NewRef(1)
|
||||
}
|
||||
|
||||
b.state.Eth1DataVotes = append(votes, val)
|
||||
b.markFieldAsDirty(eth1DataVotes)
|
||||
b.addDirtyIndices(eth1DataVotes, []uint64{uint64(len(b.state.Eth1DataVotes) - 1)})
|
||||
return nil
|
||||
}
|
||||
148
beacon-chain/state/stateV0/setters_misc.go
Normal file
148
beacon-chain/state/stateV0/setters_misc.go
Normal file
@@ -0,0 +1,148 @@
|
||||
package stateV0
|
||||
|
||||
import (
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"github.com/pkg/errors"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/hashutil"
|
||||
)
|
||||
|
||||
// SetGenesisTime for the beacon state.
|
||||
func (b *BeaconState) SetGenesisTime(val uint64) error {
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.state.GenesisTime = val
|
||||
b.markFieldAsDirty(genesisTime)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetGenesisValidatorRoot for the beacon state.
|
||||
func (b *BeaconState) SetGenesisValidatorRoot(val []byte) error {
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.state.GenesisValidatorsRoot = val
|
||||
b.markFieldAsDirty(genesisValidatorRoot)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetSlot for the beacon state.
|
||||
func (b *BeaconState) SetSlot(val types.Slot) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.state.Slot = val
|
||||
b.markFieldAsDirty(slot)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetFork version for the beacon chain.
|
||||
func (b *BeaconState) SetFork(val *pbp2p.Fork) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
fk, ok := proto.Clone(val).(*pbp2p.Fork)
|
||||
if !ok {
|
||||
return errors.New("proto.Clone did not return a fork proto")
|
||||
}
|
||||
b.state.Fork = fk
|
||||
b.markFieldAsDirty(fork)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetHistoricalRoots for the beacon state. Updates the entire
|
||||
// list to a new value by overwriting the previous one.
|
||||
func (b *BeaconState) SetHistoricalRoots(val [][]byte) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.sharedFieldReferences[historicalRoots].MinusRef()
|
||||
b.sharedFieldReferences[historicalRoots] = stateutil.NewRef(1)
|
||||
|
||||
b.state.HistoricalRoots = val
|
||||
b.markFieldAsDirty(historicalRoots)
|
||||
return nil
|
||||
}
|
||||
|
||||
// AppendHistoricalRoots for the beacon state. Appends the new value
|
||||
// to the the end of list.
|
||||
func (b *BeaconState) AppendHistoricalRoots(root [32]byte) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
roots := b.state.HistoricalRoots
|
||||
if b.sharedFieldReferences[historicalRoots].Refs() > 1 {
|
||||
roots = make([][]byte, len(b.state.HistoricalRoots))
|
||||
copy(roots, b.state.HistoricalRoots)
|
||||
b.sharedFieldReferences[historicalRoots].MinusRef()
|
||||
b.sharedFieldReferences[historicalRoots] = stateutil.NewRef(1)
|
||||
}
|
||||
|
||||
b.state.HistoricalRoots = append(roots, root[:])
|
||||
b.markFieldAsDirty(historicalRoots)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Recomputes the branch up the index in the Merkle trie representation
|
||||
// of the beacon state. This method performs map reads and the caller MUST
|
||||
// hold the lock before calling this method.
|
||||
func (b *BeaconState) recomputeRoot(idx int) {
|
||||
hashFunc := hashutil.CustomSHA256Hasher()
|
||||
layers := b.merkleLayers
|
||||
// The merkle tree structure looks as follows:
|
||||
// [[r1, r2, r3, r4], [parent1, parent2], [root]]
|
||||
// Using information about the index which changed, idx, we recompute
|
||||
// only its branch up the tree.
|
||||
currentIndex := idx
|
||||
root := b.merkleLayers[0][idx]
|
||||
for i := 0; i < len(layers)-1; i++ {
|
||||
isLeft := currentIndex%2 == 0
|
||||
neighborIdx := currentIndex ^ 1
|
||||
|
||||
neighbor := make([]byte, 32)
|
||||
if layers[i] != nil && len(layers[i]) != 0 && neighborIdx < len(layers[i]) {
|
||||
neighbor = layers[i][neighborIdx]
|
||||
}
|
||||
if isLeft {
|
||||
parentHash := hashFunc(append(root, neighbor...))
|
||||
root = parentHash[:]
|
||||
} else {
|
||||
parentHash := hashFunc(append(neighbor, root...))
|
||||
root = parentHash[:]
|
||||
}
|
||||
parentIdx := currentIndex / 2
|
||||
// Update the cached layers at the parent index.
|
||||
layers[i+1][parentIdx] = root
|
||||
currentIndex = parentIdx
|
||||
}
|
||||
b.merkleLayers = layers
|
||||
}
|
||||
|
||||
func (b *BeaconState) markFieldAsDirty(field fieldIndex) {
|
||||
_, ok := b.dirtyFields[field]
|
||||
if !ok {
|
||||
b.dirtyFields[field] = true
|
||||
}
|
||||
// do nothing if field already exists
|
||||
}
|
||||
|
||||
// addDirtyIndices adds the relevant dirty field indices, so that they
|
||||
// can be recomputed.
|
||||
func (b *BeaconState) addDirtyIndices(index fieldIndex, indices []uint64) {
|
||||
b.dirtyIndices[index] = append(b.dirtyIndices[index], indices...)
|
||||
}
|
||||
53
beacon-chain/state/stateV0/setters_randao.go
Normal file
53
beacon-chain/state/stateV0/setters_randao.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package stateV0
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
)
|
||||
|
||||
// SetRandaoMixes for the beacon state. Updates the entire
|
||||
// randao mixes to a new value by overwriting the previous one.
|
||||
func (b *BeaconState) SetRandaoMixes(val [][]byte) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.sharedFieldReferences[randaoMixes].MinusRef()
|
||||
b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1)
|
||||
|
||||
b.state.RandaoMixes = val
|
||||
b.markFieldAsDirty(randaoMixes)
|
||||
b.rebuildTrie[randaoMixes] = true
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateRandaoMixesAtIndex for the beacon state. Updates the randao mixes
|
||||
// at a specific index to a new value.
|
||||
func (b *BeaconState) UpdateRandaoMixesAtIndex(idx uint64, val []byte) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
if uint64(len(b.state.RandaoMixes)) <= idx {
|
||||
return errors.Errorf("invalid index provided %d", idx)
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
mixes := b.state.RandaoMixes
|
||||
if refs := b.sharedFieldReferences[randaoMixes].Refs(); refs > 1 {
|
||||
// Copy elements in underlying array by reference.
|
||||
mixes = make([][]byte, len(b.state.RandaoMixes))
|
||||
copy(mixes, b.state.RandaoMixes)
|
||||
b.sharedFieldReferences[randaoMixes].MinusRef()
|
||||
b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1)
|
||||
}
|
||||
|
||||
mixes[idx] = val
|
||||
b.state.RandaoMixes = mixes
|
||||
b.markFieldAsDirty(randaoMixes)
|
||||
b.addDirtyIndices(randaoMixes, []uint64{idx})
|
||||
|
||||
return nil
|
||||
}
|
||||
59
beacon-chain/state/stateV0/setters_state.go
Normal file
59
beacon-chain/state/stateV0/setters_state.go
Normal file
@@ -0,0 +1,59 @@
|
||||
package stateV0
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
)
|
||||
|
||||
// SetStateRoots for the beacon state. Updates the state roots
|
||||
// to a new value by overwriting the previous value.
|
||||
func (b *BeaconState) SetStateRoots(val [][]byte) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.sharedFieldReferences[stateRoots].MinusRef()
|
||||
b.sharedFieldReferences[stateRoots] = stateutil.NewRef(1)
|
||||
|
||||
b.state.StateRoots = val
|
||||
b.markFieldAsDirty(stateRoots)
|
||||
b.rebuildTrie[stateRoots] = true
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateStateRootAtIndex for the beacon state. Updates the state root
|
||||
// at a specific index to a new value.
|
||||
func (b *BeaconState) UpdateStateRootAtIndex(idx uint64, stateRoot [32]byte) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
|
||||
b.lock.RLock()
|
||||
if uint64(len(b.state.StateRoots)) <= idx {
|
||||
b.lock.RUnlock()
|
||||
return errors.Errorf("invalid index provided %d", idx)
|
||||
}
|
||||
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.state.StateRoots
|
||||
if ref := b.sharedFieldReferences[stateRoots]; ref.Refs() > 1 {
|
||||
// Copy elements in underlying array by reference.
|
||||
r = make([][]byte, len(b.state.StateRoots))
|
||||
copy(r, b.state.StateRoots)
|
||||
ref.MinusRef()
|
||||
b.sharedFieldReferences[stateRoots] = stateutil.NewRef(1)
|
||||
}
|
||||
|
||||
r[idx] = stateRoot[:]
|
||||
b.state.StateRoots = r
|
||||
|
||||
b.markFieldAsDirty(stateRoots)
|
||||
b.addDirtyIndices(stateRoots, []uint64{idx})
|
||||
return nil
|
||||
}
|
||||
230
beacon-chain/state/stateV0/setters_validator.go
Normal file
230
beacon-chain/state/stateV0/setters_validator.go
Normal file
@@ -0,0 +1,230 @@
|
||||
package stateV0
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
)
|
||||
|
||||
// SetValidators for the beacon state. Updates the entire
|
||||
// to a new value by overwriting the previous one.
|
||||
func (b *BeaconState) SetValidators(val []*ethpb.Validator) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.state.Validators = val
|
||||
b.sharedFieldReferences[validators].MinusRef()
|
||||
b.sharedFieldReferences[validators] = stateutil.NewRef(1)
|
||||
b.markFieldAsDirty(validators)
|
||||
b.rebuildTrie[validators] = true
|
||||
b.valMapHandler = stateutil.NewValMapHandler(b.state.Validators)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ApplyToEveryValidator applies the provided callback function to each validator in the
|
||||
// validator registry.
|
||||
func (b *BeaconState) ApplyToEveryValidator(f func(idx int, val *ethpb.Validator) (bool, *ethpb.Validator, error)) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
v := b.state.Validators
|
||||
if ref := b.sharedFieldReferences[validators]; ref.Refs() > 1 {
|
||||
v = b.validatorsReferences()
|
||||
ref.MinusRef()
|
||||
b.sharedFieldReferences[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 changed {
|
||||
changedVals = append(changedVals, uint64(i))
|
||||
v[i] = newVal
|
||||
}
|
||||
}
|
||||
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.state.Validators = v
|
||||
b.markFieldAsDirty(validators)
|
||||
b.addDirtyIndices(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 types.ValidatorIndex, val *ethpb.Validator) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
if uint64(len(b.state.Validators)) <= uint64(idx) {
|
||||
return errors.Errorf("invalid index provided %d", idx)
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
v := b.state.Validators
|
||||
if ref := b.sharedFieldReferences[validators]; ref.Refs() > 1 {
|
||||
v = b.validatorsReferences()
|
||||
ref.MinusRef()
|
||||
b.sharedFieldReferences[validators] = stateutil.NewRef(1)
|
||||
}
|
||||
|
||||
v[idx] = val
|
||||
b.state.Validators = v
|
||||
b.markFieldAsDirty(validators)
|
||||
b.addDirtyIndices(validators, []uint64{uint64(idx)})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetBalances for the beacon state. Updates the entire
|
||||
// list to a new value by overwriting the previous one.
|
||||
func (b *BeaconState) SetBalances(val []uint64) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.sharedFieldReferences[balances].MinusRef()
|
||||
b.sharedFieldReferences[balances] = stateutil.NewRef(1)
|
||||
|
||||
b.state.Balances = val
|
||||
b.markFieldAsDirty(balances)
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateBalancesAtIndex for the beacon state. This method updates the balance
|
||||
// at a specific index to a new value.
|
||||
func (b *BeaconState) UpdateBalancesAtIndex(idx types.ValidatorIndex, val uint64) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
if uint64(len(b.state.Balances)) <= uint64(idx) {
|
||||
return errors.Errorf("invalid index provided %d", idx)
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
bals := b.state.Balances
|
||||
if b.sharedFieldReferences[balances].Refs() > 1 {
|
||||
bals = b.balances()
|
||||
b.sharedFieldReferences[balances].MinusRef()
|
||||
b.sharedFieldReferences[balances] = stateutil.NewRef(1)
|
||||
}
|
||||
|
||||
bals[idx] = val
|
||||
b.state.Balances = bals
|
||||
b.markFieldAsDirty(balances)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetSlashings for the beacon state. Updates the entire
|
||||
// list to a new value by overwriting the previous one.
|
||||
func (b *BeaconState) SetSlashings(val []uint64) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.sharedFieldReferences[slashings].MinusRef()
|
||||
b.sharedFieldReferences[slashings] = stateutil.NewRef(1)
|
||||
|
||||
b.state.Slashings = val
|
||||
b.markFieldAsDirty(slashings)
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateSlashingsAtIndex for the beacon state. Updates the slashings
|
||||
// at a specific index to a new value.
|
||||
func (b *BeaconState) UpdateSlashingsAtIndex(idx, val uint64) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
if uint64(len(b.state.Slashings)) <= idx {
|
||||
return errors.Errorf("invalid index provided %d", idx)
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
s := b.state.Slashings
|
||||
if b.sharedFieldReferences[slashings].Refs() > 1 {
|
||||
s = b.slashings()
|
||||
b.sharedFieldReferences[slashings].MinusRef()
|
||||
b.sharedFieldReferences[slashings] = stateutil.NewRef(1)
|
||||
}
|
||||
|
||||
s[idx] = val
|
||||
|
||||
b.state.Slashings = s
|
||||
|
||||
b.markFieldAsDirty(slashings)
|
||||
return nil
|
||||
}
|
||||
|
||||
// AppendValidator for the beacon state. Appends the new value
|
||||
// to the the end of list.
|
||||
func (b *BeaconState) AppendValidator(val *ethpb.Validator) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
vals := b.state.Validators
|
||||
if b.sharedFieldReferences[validators].Refs() > 1 {
|
||||
vals = b.validatorsReferences()
|
||||
b.sharedFieldReferences[validators].MinusRef()
|
||||
b.sharedFieldReferences[validators] = stateutil.NewRef(1)
|
||||
}
|
||||
|
||||
// append validator to slice
|
||||
b.state.Validators = append(vals, val)
|
||||
valIdx := types.ValidatorIndex(len(b.state.Validators) - 1)
|
||||
|
||||
// Copy if this is a shared validator map
|
||||
if ref := b.valMapHandler.MapRef(); ref.Refs() > 1 {
|
||||
valMap := b.valMapHandler.Copy()
|
||||
ref.MinusRef()
|
||||
b.valMapHandler = valMap
|
||||
}
|
||||
b.valMapHandler.Set(bytesutil.ToBytes48(val.PublicKey), valIdx)
|
||||
|
||||
b.markFieldAsDirty(validators)
|
||||
b.addDirtyIndices(validators, []uint64{uint64(valIdx)})
|
||||
return nil
|
||||
}
|
||||
|
||||
// AppendBalance for the beacon state. Appends the new value
|
||||
// to the the end of list.
|
||||
func (b *BeaconState) AppendBalance(bal uint64) error {
|
||||
if !b.hasInnerState() {
|
||||
return ErrNilInnerState
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
bals := b.state.Balances
|
||||
if b.sharedFieldReferences[balances].Refs() > 1 {
|
||||
bals = b.balances()
|
||||
b.sharedFieldReferences[balances].MinusRef()
|
||||
b.sharedFieldReferences[balances] = stateutil.NewRef(1)
|
||||
}
|
||||
|
||||
b.state.Balances = append(bals, bal)
|
||||
b.markFieldAsDirty(balances)
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user