mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-09 21:38:05 -05:00
committed by
terence tsao
parent
c2deace3f4
commit
249ec8751b
@@ -21,6 +21,8 @@ go_library(
|
||||
"//shared/mathutil:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
"//shared/ssz:go_default_library",
|
||||
"@org_golang_google_grpc//codes:go_default_library",
|
||||
"@org_golang_google_grpc//status:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -39,5 +41,7 @@ go_test(
|
||||
"//proto/beacon/p2p/v1:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
"@com_github_gogo_protobuf//proto:go_default_library",
|
||||
"@org_golang_google_grpc//codes:go_default_library",
|
||||
"@org_golang_google_grpc//status:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -13,6 +13,8 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/mathutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// CrosslinkCommittee defines the validator committee of slot and shard combinations.
|
||||
@@ -377,6 +379,7 @@ func CommitteeAssignment(
|
||||
slot uint64,
|
||||
validatorIndex uint64,
|
||||
registryChange bool) ([]uint64, uint64, uint64, bool, error) {
|
||||
var selectedCommittees []*CrosslinkCommittee
|
||||
|
||||
wantedEpoch := slot / params.BeaconConfig().SlotsPerEpoch
|
||||
prevEpoch := PrevEpoch(state)
|
||||
@@ -391,36 +394,31 @@ func CommitteeAssignment(
|
||||
)
|
||||
}
|
||||
|
||||
crosslinkCommittees, err := CrosslinkCommitteesAtSlot(
|
||||
state, slot, registryChange)
|
||||
if err != nil {
|
||||
return []uint64{}, 0, 0, false, fmt.Errorf("could not get crosslink committee: %v", err)
|
||||
}
|
||||
return ValidatorAssignment(validatorIndex, slot, crosslinkCommittees)
|
||||
}
|
||||
startSlot := StartSlot(wantedEpoch)
|
||||
for slot := startSlot; slot < startSlot+params.BeaconConfig().SlotsPerEpoch; slot++ {
|
||||
crosslinkCommittees, err := CrosslinkCommitteesAtSlot(
|
||||
state, slot, registryChange)
|
||||
if err != nil {
|
||||
return []uint64{}, 0, 0, false, fmt.Errorf("could not get crosslink committee: %v", err)
|
||||
}
|
||||
for _, committee := range crosslinkCommittees {
|
||||
for _, idx := range committee.Committee {
|
||||
if idx == validatorIndex {
|
||||
selectedCommittees = append(selectedCommittees, committee)
|
||||
}
|
||||
|
||||
// ValidatorAssignment takes individual validator's index and returns its committee list,
|
||||
// assigned shard, slot and role.
|
||||
func ValidatorAssignment(vIndex uint64, slot uint64, committees []*CrosslinkCommittee) ([]uint64, uint64, uint64, bool, error) {
|
||||
var selectedCommittees []*CrosslinkCommittee
|
||||
for _, committee := range committees {
|
||||
for _, idx := range committee.Committee {
|
||||
if idx == vIndex {
|
||||
selectedCommittees = append(selectedCommittees, committee)
|
||||
}
|
||||
|
||||
if len(selectedCommittees) > 0 {
|
||||
validators := selectedCommittees[0].Committee
|
||||
shard := selectedCommittees[0].Shard
|
||||
firstCommitteeAtSlot := committees[0].Committee
|
||||
isProposer := firstCommitteeAtSlot[slot%
|
||||
uint64(len(firstCommitteeAtSlot))] == vIndex
|
||||
return validators, shard, slot, isProposer, nil
|
||||
if len(selectedCommittees) > 0 {
|
||||
validators := selectedCommittees[0].Committee
|
||||
shard := selectedCommittees[0].Shard
|
||||
firstCommitteeAtSlot := crosslinkCommittees[0].Committee
|
||||
isProposer := firstCommitteeAtSlot[slot%
|
||||
uint64(len(firstCommitteeAtSlot))] == validatorIndex
|
||||
return validators, shard, slot, isProposer, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return []uint64{}, 0, 0, false, fmt.Errorf("unable to find assignment for "+
|
||||
"validator %d at slot %d", vIndex, slot)
|
||||
return []uint64{}, 0, 0, false, status.Error(codes.NotFound, "validator not found found in assignments")
|
||||
}
|
||||
|
||||
// prevEpochCommitteesAtSlot returns a list of crosslink committees of the previous epoch.
|
||||
|
||||
@@ -8,6 +8,8 @@ import (
|
||||
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
var size = 1<<(params.BeaconConfig().RandBytes*8) - 1
|
||||
@@ -496,11 +498,12 @@ func TestCommitteeAssignment_CantFindValidator(t *testing.T) {
|
||||
Slot: params.BeaconConfig().GenesisSlot + params.BeaconConfig().SlotsPerEpoch,
|
||||
}
|
||||
index := uint64(10000)
|
||||
want := fmt.Sprintf(
|
||||
"unable to find assignment for validator %d at slot %d",
|
||||
index, params.BeaconConfig().GenesisSlot+params.BeaconConfig().SlotsPerEpoch)
|
||||
_, _, _, _, err := CommitteeAssignment(state, state.Slot, index, false)
|
||||
if !strings.Contains(err.Error(), want) {
|
||||
t.Errorf("Expected: %s, received: %v", want, err)
|
||||
statusErr, ok := status.FromError(err)
|
||||
if !ok {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if statusErr.Code() != codes.NotFound {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ go_library(
|
||||
srcs = [
|
||||
"attester_server.go",
|
||||
"beacon_server.go",
|
||||
"committees_cache.go",
|
||||
"proposer_server.go",
|
||||
"service.go",
|
||||
"validator_server.go",
|
||||
@@ -32,17 +31,11 @@ go_library(
|
||||
"@com_github_grpc_ecosystem_go_grpc_middleware//:go_default_library",
|
||||
"@com_github_grpc_ecosystem_go_grpc_middleware//recovery:go_default_library",
|
||||
"@com_github_grpc_ecosystem_go_grpc_prometheus//:go_default_library",
|
||||
"@com_github_prometheus_client_golang//prometheus:go_default_library",
|
||||
"@com_github_prometheus_client_golang//prometheus/promauto:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@io_k8s_client_go//tools/cache:go_default_library",
|
||||
"@io_opencensus_go//plugin/ocgrpc:go_default_library",
|
||||
"@io_opencensus_go//trace:go_default_library",
|
||||
"@org_golang_google_grpc//:go_default_library",
|
||||
"@org_golang_google_grpc//codes:go_default_library",
|
||||
"@org_golang_google_grpc//credentials:go_default_library",
|
||||
"@org_golang_google_grpc//reflection:go_default_library",
|
||||
"@org_golang_google_grpc//status:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -51,7 +44,6 @@ go_test(
|
||||
srcs = [
|
||||
"attester_server_test.go",
|
||||
"beacon_server_test.go",
|
||||
"committee_cache_test.go",
|
||||
"proposer_server_test.go",
|
||||
"service_test.go",
|
||||
"validator_server_test.go",
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
package rpc
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
)
|
||||
|
||||
func TestSlotKeyFn_OK(t *testing.T) {
|
||||
cInfo := &committeesInfo{
|
||||
slot: 999,
|
||||
committees: []*helpers.CrosslinkCommittee{
|
||||
{Shard: 1, Committee: []uint64{1, 2, 3}},
|
||||
{Shard: 1, Committee: []uint64{4, 5, 6}},
|
||||
},
|
||||
}
|
||||
|
||||
key, err := slotKeyFn(cInfo)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if key != strconv.Itoa(cInfo.slot) {
|
||||
t.Errorf("Incorrect hash key: %s, expected %s", key, strconv.Itoa(cInfo.slot))
|
||||
}
|
||||
}
|
||||
|
||||
func TestSlotKeyFn_InvalidObj(t *testing.T) {
|
||||
_, err := slotKeyFn("bad")
|
||||
if err != ErrNotACommitteeInfo {
|
||||
t.Errorf("Expected error %v, got %v", ErrNotACommitteeInfo, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCommitteesCache_CommitteesInfoBySlot(t *testing.T) {
|
||||
cache := newCommitteesCache()
|
||||
|
||||
cInfo := &committeesInfo{
|
||||
slot: 123,
|
||||
committees: []*helpers.CrosslinkCommittee{{Shard: 456}},
|
||||
}
|
||||
|
||||
exists, _, err := cache.CommitteesInfoBySlot(cInfo.slot)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if exists {
|
||||
t.Error("Expected committees info not to exist in empty cache")
|
||||
}
|
||||
|
||||
if err := cache.AddCommittees(cInfo); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
exists, fetchedInfo, err := cache.CommitteesInfoBySlot(cInfo.slot)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !exists {
|
||||
t.Error("Expected committee info to exist")
|
||||
}
|
||||
if fetchedInfo.slot != cInfo.slot {
|
||||
t.Errorf(
|
||||
"Expected fetched slot number to be %d, got %d",
|
||||
cInfo.slot,
|
||||
fetchedInfo.slot,
|
||||
)
|
||||
}
|
||||
if !reflect.DeepEqual(fetchedInfo.committees, cInfo.committees) {
|
||||
t.Errorf(
|
||||
"Expected fetched info committee to be %v, got %v",
|
||||
cInfo.committees,
|
||||
fetchedInfo.committees,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBlockCache_maxSize(t *testing.T) {
|
||||
cache := newCommitteesCache()
|
||||
|
||||
for i := 0; i < maxCacheSize+10; i++ {
|
||||
cInfo := &committeesInfo{
|
||||
slot: i,
|
||||
}
|
||||
if err := cache.AddCommittees(cInfo); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
if len(cache.committeesCache.ListKeys()) != maxCacheSize {
|
||||
t.Errorf(
|
||||
"Expected hash cache key size to be %d, got %d",
|
||||
maxCacheSize,
|
||||
len(cache.committeesCache.ListKeys()),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
package rpc
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrNotACommitteeInfo will be returned when a cache object is not a pointer to
|
||||
// a committeeInfo struct.
|
||||
ErrNotACommitteeInfo = errors.New("object is not an committee info")
|
||||
|
||||
// maxCacheSize is 4x of the epoch length for additional cache padding.
|
||||
// Requests should be only accessing committees within defined epoch length.
|
||||
maxCacheSize = int(2 * params.BeaconConfig().SlotsPerEpoch)
|
||||
|
||||
// Metrics
|
||||
committeeCacheMiss = promauto.NewCounter(prometheus.CounterOpts{
|
||||
Name: "committee_cache_miss",
|
||||
Help: "The number of committee requests that aren't present in the cache.",
|
||||
})
|
||||
committeeCacheHit = promauto.NewCounter(prometheus.CounterOpts{
|
||||
Name: "committee_cache_hit",
|
||||
Help: "The number of committee requests that are present in the cache.",
|
||||
})
|
||||
committeeCacheSize = promauto.NewGauge(prometheus.GaugeOpts{
|
||||
Name: "committee_cache_size",
|
||||
Help: "The number of committees in the committee cache",
|
||||
})
|
||||
)
|
||||
|
||||
// committeesInfo species the committee information of a given slot.
|
||||
type committeesInfo struct {
|
||||
slot int
|
||||
committees []*helpers.CrosslinkCommittee
|
||||
}
|
||||
|
||||
// committeesCache struct with 1 queue for looking up crosslink committees by slot.
|
||||
type committeesCache struct {
|
||||
committeesCache *cache.FIFO
|
||||
lock sync.RWMutex
|
||||
}
|
||||
|
||||
// slotKeyFn takes the string representation of the slot number as the key
|
||||
// for a committeeInfo.
|
||||
func slotKeyFn(obj interface{}) (string, error) {
|
||||
cInfo, ok := obj.(*committeesInfo)
|
||||
if !ok {
|
||||
return "", ErrNotACommitteeInfo
|
||||
}
|
||||
|
||||
return strconv.Itoa(cInfo.slot), nil
|
||||
}
|
||||
|
||||
// newCommitteesCache creates a new committee cache for storing/accessing blockInfo from
|
||||
// memory.
|
||||
func newCommitteesCache() *committeesCache {
|
||||
return &committeesCache{
|
||||
committeesCache: cache.NewFIFO(slotKeyFn),
|
||||
}
|
||||
}
|
||||
|
||||
// CommitteesInfoBySlot fetches committeesInfo by slot. Returns true with a
|
||||
// reference to the committees info, if exists. Otherwise returns false, nil.
|
||||
func (c *committeesCache) CommitteesInfoBySlot(slot int) (bool, *committeesInfo, error) {
|
||||
c.lock.RLock()
|
||||
defer c.lock.RUnlock()
|
||||
|
||||
obj, exists, err := c.committeesCache.GetByKey(strconv.Itoa(slot))
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
|
||||
if exists {
|
||||
committeeCacheHit.Inc()
|
||||
} else {
|
||||
committeeCacheMiss.Inc()
|
||||
return false, nil, nil
|
||||
}
|
||||
|
||||
cInfo, ok := obj.(*committeesInfo)
|
||||
if !ok {
|
||||
return false, nil, ErrNotACommitteeInfo
|
||||
}
|
||||
|
||||
return true, cInfo, nil
|
||||
}
|
||||
|
||||
// AddCommittees adds committeeInfo object to the cache. This method also trims the least
|
||||
// recently added committeeInfo object if the cache size has ready the max cache size limit.
|
||||
func (c *committeesCache) AddCommittees(committees *committeesInfo) error {
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
|
||||
if err := c.committeesCache.AddIfNotPresent(committees); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
trim(c.committeesCache, maxCacheSize)
|
||||
committeeCacheSize.Set(float64(len(c.committeesCache.ListKeys())))
|
||||
return nil
|
||||
}
|
||||
|
||||
// trim the FIFO queue to the maxSize.
|
||||
func trim(queue *cache.FIFO, maxSize int) {
|
||||
for s := len(queue.ListKeys()); s > maxSize; s-- {
|
||||
// #nosec G104 popProcessNoopFunc never returns an error
|
||||
_, _ = queue.Pop(popProcessNoopFunc)
|
||||
}
|
||||
}
|
||||
|
||||
// popProcessNoopFunc is a no-op function that never returns an error.
|
||||
func popProcessNoopFunc(obj interface{}) error {
|
||||
return nil
|
||||
}
|
||||
@@ -71,7 +71,6 @@ type Service struct {
|
||||
canonicalStateChan chan *pbp2p.BeaconState
|
||||
incomingAttestation chan *pbp2p.Attestation
|
||||
credentialError error
|
||||
committeesCache *committeesCache // cache to store committees info.
|
||||
}
|
||||
|
||||
// Config options for the beacon node RPC server.
|
||||
@@ -101,7 +100,6 @@ func NewRPCService(ctx context.Context, cfg *Config) *Service {
|
||||
withKey: cfg.KeyFlag,
|
||||
canonicalStateChan: make(chan *pbp2p.BeaconState, params.BeaconConfig().DefaultBufferSize),
|
||||
incomingAttestation: make(chan *pbp2p.Attestation, params.BeaconConfig().DefaultBufferSize),
|
||||
committeesCache: newCommitteesCache(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,7 +164,6 @@ func (s *Service) Start() {
|
||||
beaconDB: s.beaconDB,
|
||||
chainService: s.chainService,
|
||||
canonicalStateChan: s.canonicalStateChan,
|
||||
committeesCache: s.committeesCache,
|
||||
}
|
||||
pb.RegisterBeaconServiceServer(s.grpcServer, beaconServer)
|
||||
pb.RegisterProposerServiceServer(s.grpcServer, proposerServer)
|
||||
|
||||
@@ -11,12 +11,8 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/db"
|
||||
pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/rpc/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/hashutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"go.opencensus.io/trace"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// ValidatorServer defines a server implementation of the gRPC Validator service,
|
||||
@@ -28,7 +24,6 @@ type ValidatorServer struct {
|
||||
beaconDB *db.BeaconDB
|
||||
chainService chainService
|
||||
canonicalStateChan chan *pbp2p.BeaconState
|
||||
committeesCache *committeesCache
|
||||
}
|
||||
|
||||
// WaitForActivation checks if a validator public key exists in the active validator registry of the current
|
||||
@@ -121,7 +116,6 @@ func (vs *ValidatorServer) ValidatorPerformance(
|
||||
func (vs *ValidatorServer) CommitteeAssignment(
|
||||
ctx context.Context,
|
||||
req *pb.CommitteeAssignmentsRequest) (*pb.CommitteeAssignmentResponse, error) {
|
||||
|
||||
beaconState, err := vs.beaconDB.HeadState(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not fetch beacon state: %v", err)
|
||||
@@ -146,9 +140,6 @@ func (vs *ValidatorServer) assignment(
|
||||
epochStart uint64,
|
||||
) (*pb.CommitteeAssignmentResponse_CommitteeAssignment, error) {
|
||||
|
||||
ctx, span := trace.StartSpan(ctx, "beacon-chain.rpcservice.CommitteeAssignment.assignment")
|
||||
defer span.End()
|
||||
|
||||
if len(pubkey) != params.BeaconConfig().BLSPubkeyLength {
|
||||
return nil, fmt.Errorf(
|
||||
"expected public key to have length %d, received %d",
|
||||
@@ -159,9 +150,8 @@ func (vs *ValidatorServer) assignment(
|
||||
|
||||
idx, err := vs.beaconDB.ValidatorIndex(pubkey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("could not get active validator index: %v", err)
|
||||
}
|
||||
|
||||
chainHead, err := vs.beaconDB.ChainHead()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get chain head: %v", err)
|
||||
@@ -179,64 +169,23 @@ func (vs *ValidatorServer) assignment(
|
||||
}
|
||||
}
|
||||
|
||||
vStatus, err := vs.validatorStatus(pubkey, beaconState)
|
||||
committee, shard, slot, isProposer, err :=
|
||||
helpers.CommitteeAssignment(beaconState, epochStart, uint64(idx), false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for slot := epochStart; slot < epochStart+params.BeaconConfig().SlotsPerEpoch; slot++ {
|
||||
if featureconfig.FeatureConfig().EnableCommitteesCache {
|
||||
if exists, committees, err := vs.committeesCache.CommitteesInfoBySlot(int(slot)); exists || err != nil {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
span.AddAttributes(trace.BoolAttribute("committeeCacheHit", true))
|
||||
committee, shard, slot, isProposer, err :=
|
||||
helpers.ValidatorAssignment(idx, slot, committees.committees)
|
||||
if err == nil {
|
||||
return &pb.CommitteeAssignmentResponse_CommitteeAssignment{
|
||||
Committee: committee,
|
||||
Shard: shard,
|
||||
Slot: slot,
|
||||
IsProposer: isProposer,
|
||||
PublicKey: pubkey,
|
||||
Status: vStatus,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
committees, err := helpers.CrosslinkCommitteesAtSlot(
|
||||
beaconState,
|
||||
slot,
|
||||
false /* registeryChange */)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if featureconfig.FeatureConfig().EnableCommitteesCache {
|
||||
committeesInfo := &committeesInfo{
|
||||
slot: int(slot),
|
||||
committees: committees,
|
||||
}
|
||||
span.AddAttributes(trace.BoolAttribute("committeeCacheHit", false))
|
||||
if err := vs.committeesCache.AddCommittees(committeesInfo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
committee, shard, slot, isProposer, err :=
|
||||
helpers.ValidatorAssignment(idx, slot, committees)
|
||||
if err == nil {
|
||||
return &pb.CommitteeAssignmentResponse_CommitteeAssignment{
|
||||
Committee: committee,
|
||||
Shard: shard,
|
||||
Slot: slot,
|
||||
IsProposer: isProposer,
|
||||
PublicKey: pubkey,
|
||||
Status: vStatus,
|
||||
}, nil
|
||||
}
|
||||
status, err := vs.validatorStatus(pubkey, beaconState)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, status.Error(codes.NotFound, "validator not found found in assignments")
|
||||
return &pb.CommitteeAssignmentResponse_CommitteeAssignment{
|
||||
Committee: committee,
|
||||
Shard: shard,
|
||||
Slot: slot,
|
||||
IsProposer: isProposer,
|
||||
PublicKey: pubkey,
|
||||
Status: status,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ValidatorStatus returns the validator status of the current epoch.
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -18,16 +17,9 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/internal"
|
||||
pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/rpc/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
)
|
||||
|
||||
func init() {
|
||||
featureconfig.InitFeatureConfig(&featureconfig.FeatureFlagConfig{
|
||||
EnableCommitteesCache: true,
|
||||
})
|
||||
}
|
||||
|
||||
func genesisState(validators uint64) (*pbp2p.BeaconState, error) {
|
||||
genesisTime := time.Unix(0, 0).Unix()
|
||||
deposits := make([]*pbp2p.Deposit, validators)
|
||||
@@ -111,7 +103,7 @@ func TestNextEpochCommitteeAssignment_CantFindValidatorIdx(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCommitteeAssignment_CacheMissOk(t *testing.T) {
|
||||
func TestCommitteeAssignment_OK(t *testing.T) {
|
||||
db := internal.SetupDB(t)
|
||||
defer internal.TeardownDB(t, db)
|
||||
ctx := context.Background()
|
||||
@@ -148,8 +140,7 @@ func TestCommitteeAssignment_CacheMissOk(t *testing.T) {
|
||||
}
|
||||
|
||||
vs := &ValidatorServer{
|
||||
beaconDB: db,
|
||||
committeesCache: newCommitteesCache(),
|
||||
beaconDB: db,
|
||||
}
|
||||
|
||||
pubKeyBuf := make([]byte, params.BeaconConfig().BLSPubkeyLength)
|
||||
@@ -194,7 +185,7 @@ func TestCommitteeAssignment_CacheMissOk(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCommitteeAssignment_MultipleKeys_CacheHitOk(t *testing.T) {
|
||||
func TestCommitteeAssignment_multipleKeys_OK(t *testing.T) {
|
||||
db := internal.SetupDB(t)
|
||||
defer internal.TeardownDB(t, db)
|
||||
ctx := context.Background()
|
||||
@@ -231,51 +222,23 @@ func TestCommitteeAssignment_MultipleKeys_CacheHitOk(t *testing.T) {
|
||||
}
|
||||
|
||||
vs := &ValidatorServer{
|
||||
|
||||
beaconDB: db,
|
||||
committeesCache: newCommitteesCache(),
|
||||
beaconDB: db,
|
||||
}
|
||||
|
||||
pubKeyBuf0 := make([]byte, params.BeaconConfig().BLSPubkeyLength)
|
||||
binary.PutUvarint(pubKeyBuf0, 0)
|
||||
pubKeyBuf1 := make([]byte, params.BeaconConfig().BLSPubkeyLength)
|
||||
binary.PutUvarint(pubKeyBuf1, 1)
|
||||
binary.PutUvarint(pubKeyBuf1, 0)
|
||||
// Test the first validator in registry.
|
||||
req := &pb.CommitteeAssignmentsRequest{
|
||||
PublicKeys: [][]byte{pubKeyBuf0, pubKeyBuf1},
|
||||
EpochStart: params.BeaconConfig().GenesisSlot,
|
||||
}
|
||||
cInfo := &committeesInfo{
|
||||
slot: int(params.BeaconConfig().GenesisSlot),
|
||||
committees: []*helpers.CrosslinkCommittee{
|
||||
{Shard: 123, Committee: []uint64{0, 10, 5}},
|
||||
{Shard: 234, Committee: []uint64{1, 2, 3}},
|
||||
}}
|
||||
if err := vs.committeesCache.AddCommittees(cInfo); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
res, err := vs.CommitteeAssignment(context.Background(), req)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not call epoch committee assignment %v", err)
|
||||
}
|
||||
|
||||
if res.Assignment[0].Shard != cInfo.committees[0].Shard {
|
||||
t.Errorf("Assigned shard %d is not equal to %d",
|
||||
res.Assignment[0].Shard, cInfo.committees[0].Shard)
|
||||
}
|
||||
if !reflect.DeepEqual(res.Assignment[0].Committee, cInfo.committees[0].Committee) {
|
||||
t.Errorf("Expected committee to be %v, got %v",
|
||||
cInfo.committees[0].Committee, res.Assignment[0].Committee)
|
||||
}
|
||||
if res.Assignment[1].Shard != cInfo.committees[1].Shard {
|
||||
t.Errorf("Assigned shard %d is not equal to %d",
|
||||
res.Assignment[1].Shard, cInfo.committees[1].Shard)
|
||||
}
|
||||
if !reflect.DeepEqual(res.Assignment[1].Committee, cInfo.committees[1].Committee) {
|
||||
t.Errorf("Expected committee to be %v, got %v",
|
||||
cInfo.committees[1].Committee, res.Assignment[1].Committee)
|
||||
}
|
||||
|
||||
if len(res.Assignment) != 2 {
|
||||
t.Fatalf("expected 2 assignments but got %d", len(res.Assignment))
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@ type FeatureFlagConfig struct {
|
||||
EnableCrosslinks bool // EnableCrosslinks in epoch processing.
|
||||
EnableCheckBlockStateRoot bool // EnableCheckBlockStateRoot in block processing.
|
||||
EnableHistoricalStatePruning bool // EnableHistoricalStatePruning when updatifinalized states.
|
||||
EnableCommitteesCache bool // EnableCommitteesCache for RPC server.
|
||||
}
|
||||
|
||||
var featureConfig *FeatureFlagConfig
|
||||
@@ -61,10 +60,6 @@ func ConfigureBeaconFeatures(ctx *cli.Context) {
|
||||
log.Info("Enabled crosslink computations")
|
||||
cfg.EnableCrosslinks = true
|
||||
}
|
||||
if ctx.GlobalBool(EnableCommitteesCacheFlag.Name) {
|
||||
log.Info("Enabled committees cache")
|
||||
cfg.EnableCommitteesCache = true
|
||||
}
|
||||
if ctx.GlobalBool(EnableCheckBlockStateRootFlag.Name) {
|
||||
log.Info("Enabled check block state root")
|
||||
cfg.EnableCheckBlockStateRoot = true
|
||||
@@ -73,6 +68,7 @@ func ConfigureBeaconFeatures(ctx *cli.Context) {
|
||||
log.Info("Enabled historical state pruning")
|
||||
cfg.EnableHistoricalStatePruning = true
|
||||
}
|
||||
|
||||
InitFeatureConfig(cfg)
|
||||
}
|
||||
|
||||
|
||||
@@ -24,11 +24,6 @@ var (
|
||||
Name: "enable-crosslinks",
|
||||
Usage: "Enable crosslinks in epoch processing, default is disabled.",
|
||||
}
|
||||
// EnableCommitteesCacheFlag enables crosslink committees cache for rpc server. It is disabled by default.
|
||||
EnableCommitteesCacheFlag = cli.BoolFlag{
|
||||
Name: "enable-committees-cache",
|
||||
Usage: "Enable crosslink committees cache for rpc server, default is disabled.",
|
||||
}
|
||||
// EnableCheckBlockStateRootFlag check block state root in block processing. It is disabled by default.
|
||||
EnableCheckBlockStateRootFlag = cli.BoolFlag{
|
||||
Name: "enable-check-block-state-root",
|
||||
@@ -48,7 +43,6 @@ var ValidatorFlags = []cli.Flag{}
|
||||
var BeaconChainFlags = []cli.Flag{
|
||||
EnableComputeStateRootFlag,
|
||||
EnableCrosslinksFlag,
|
||||
EnableCommitteesCacheFlag,
|
||||
EnableCheckBlockStateRootFlag,
|
||||
EnableHistoricalStatePruningFlag,
|
||||
}
|
||||
|
||||
@@ -97,9 +97,9 @@ func run(ctx context.Context, v Validator) {
|
||||
|
||||
func handleAssignmentError(err error, slot uint64) {
|
||||
if errCode, ok := status.FromError(err); ok && errCode.Code() == codes.NotFound {
|
||||
log.Warnf("Validator not yet assigned between slots %d - %d",
|
||||
slot - params.BeaconConfig().GenesisSlot,
|
||||
slot + params.BeaconConfig().SlotsPerEpoch - params.BeaconConfig().GenesisSlot)
|
||||
log.WithField(
|
||||
"epoch", (slot/params.BeaconConfig().SlotsPerEpoch)-params.BeaconConfig().GenesisEpoch,
|
||||
).Warn("Validator not yet assigned to epoch")
|
||||
} else {
|
||||
log.WithField("error", err).Error("Failed to update assignments")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user