2021-07-27 15:47:03 +00:00
|
|
|
package v2
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"encoding/binary"
|
|
|
|
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
2021-09-21 19:59:25 +00:00
|
|
|
"github.com/prysmaticlabs/prysm/config/params"
|
2021-09-15 22:55:11 +00:00
|
|
|
"github.com/prysmaticlabs/prysm/crypto/hash"
|
2021-09-21 15:02:48 +00:00
|
|
|
"github.com/prysmaticlabs/prysm/encoding/ssz"
|
2021-07-27 15:47:03 +00:00
|
|
|
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
|
|
|
)
|
|
|
|
|
|
|
|
func (h *stateRootHasher) validatorRegistryRoot(validators []*ethpb.Validator) ([32]byte, error) {
|
|
|
|
hashKeyElements := make([]byte, len(validators)*32)
|
|
|
|
roots := make([][32]byte, len(validators))
|
2021-09-15 22:55:11 +00:00
|
|
|
emptyKey := hash.FastSum256(hashKeyElements)
|
|
|
|
hasher := hash.CustomSHA256Hasher()
|
2021-07-27 15:47:03 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2021-09-15 22:55:11 +00:00
|
|
|
hashKey := hash.FastSum256(hashKeyElements)
|
2021-07-27 15:47:03 +00:00
|
|
|
if hashKey != emptyKey && h.rootsCache != nil {
|
|
|
|
if found, ok := h.rootsCache.Get(string(hashKey[:])); found != nil && ok {
|
|
|
|
return found.([32]byte), nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-21 15:02:48 +00:00
|
|
|
validatorsRootsRoot, err := ssz.BitwiseMerkleizeArrays(hasher, roots, uint64(len(roots)), params.BeaconConfig().ValidatorRegistryLimit)
|
2021-07-27 15:47:03 +00:00
|
|
|
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())
|
2021-09-21 15:02:48 +00:00
|
|
|
res := ssz.MixInLength(validatorsRootsRoot, validatorsRootsBufRoot[:])
|
2021-07-27 15:47:03 +00:00
|
|
|
if hashKey != emptyKey && h.rootsCache != nil {
|
|
|
|
h.rootsCache.Set(string(hashKey[:]), res, 32)
|
|
|
|
}
|
|
|
|
return res, nil
|
|
|
|
}
|
|
|
|
|
2021-09-21 15:02:48 +00:00
|
|
|
func (h *stateRootHasher) validatorRoot(hasher ssz.HashFn, validator *ethpb.Validator) ([32]byte, error) {
|
2021-07-27 15:47:03 +00:00
|
|
|
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
|
|
|
|
}
|