prysm-pulse/beacon-chain/rpc/validator_server.go

91 lines
2.9 KiB
Go

package rpc
import (
"context"
"fmt"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
v "github.com/prysmaticlabs/prysm/beacon-chain/core/validators"
"github.com/prysmaticlabs/prysm/beacon-chain/db"
pb "github.com/prysmaticlabs/prysm/proto/beacon/rpc/v1"
"github.com/prysmaticlabs/prysm/shared/params"
)
// ValidatorServer defines a server implementation of the gRPC Validator service,
// providing RPC endpoints for obtaining validator assignments per epoch, the slots
// and shards in which particular validators need to perform their responsibilities,
// and more.
type ValidatorServer struct {
beaconDB *db.BeaconDB
}
// ValidatorIndex is called by a validator to get its index location that corresponds
// to the attestation bit fields.
func (vs *ValidatorServer) ValidatorIndex(ctx context.Context, req *pb.ValidatorIndexRequest) (*pb.ValidatorIndexResponse, error) {
beaconState, err := vs.beaconDB.State()
if err != nil {
return nil, fmt.Errorf("could not get beacon state: %v", err)
}
index, err := v.ValidatorIdx(
req.PublicKey,
beaconState.ValidatorRegistry,
)
if err != nil {
return nil, fmt.Errorf("could not get validator index: %v", err)
}
return &pb.ValidatorIndexResponse{Index: index}, nil
}
// ValidatorEpochAssignments fetches an assignment object for a validator by public key
// such as the slot the validator needs to attest in during the epoch as well as a slot
// in which the validator may need to propose during the epoch in addition to the assigned shard.
func (vs *ValidatorServer) ValidatorEpochAssignments(
ctx context.Context,
req *pb.ValidatorEpochAssignmentsRequest,
) (*pb.ValidatorEpochAssignmentsResponse, error) {
if len(req.PublicKey) != 48 {
return nil, fmt.Errorf("expected 48 byte public key, received %d", len(req.PublicKey))
}
beaconState, err := vs.beaconDB.State()
if err != nil {
return nil, fmt.Errorf("could not get beacon state: %v", err)
}
validatorIndex, err := v.ValidatorIdx(req.PublicKey, beaconState.ValidatorRegistry)
if err != nil {
return nil, fmt.Errorf("could not get active validator index: %v", err)
}
var shard uint64
var attesterSlot uint64
var proposerSlot uint64
for slot := req.EpochStart; slot < req.EpochStart+params.BeaconConfig().EpochLength; slot++ {
crossLinkCommittees, err := helpers.CrosslinkCommitteesAtSlot(beaconState, slot, false)
if err != nil {
return nil, err
}
proposerIndex, err := v.BeaconProposerIdx(beaconState, slot)
if err != nil {
return nil, err
}
if proposerIndex == validatorIndex {
proposerSlot = slot
}
for _, committee := range crossLinkCommittees {
for _, idx := range committee.Committee {
if idx == validatorIndex {
attesterSlot = slot
shard = committee.Shard
}
}
}
}
return &pb.ValidatorEpochAssignmentsResponse{
Assignment: &pb.Assignment{
PublicKey: req.PublicKey,
Shard: shard,
AttesterSlot: attesterSlot,
ProposerSlot: proposerSlot,
},
}, nil
}