mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-28 14:17:17 +00:00
cc741ed8af
* begin state service * begin on the state trie idea * created beacon state structure * add in the full clone getter * return by value instead * add all setters * new state setters are being completed * arrays roots exposed * close to finishing all these headerssss * functionality complete * added in proto benchmark test * test for compatibility * add test for compat * comments fixed * add clone * add clone * remove underlying copies * make it immutable * integrate it into chainservice * revert * wrap up comments for package * address all comments and godocs * address all comments * clone the pending attestation properly * properly clone remaining items * tests pass fixed bug * begin using it instead of head state * prevent nil pointer exceptions * begin using new struct in db * integrated new type into db package * add proper nil checks * using new state in archiver * refactored much of core * editing all the precompute functions * done with most core refactor * fixed up some bugs in the clone comparisons * append current epoch atts * add missing setters * add new setters * fix other core methods * fix up transition * main service and forkchoice * fix rpc * integrated to powchain * some more changes * fix build * improve processing of deposits * fix error * prevent panic * comment * fix process att * gaz * fix up att process * resolve existing review comments * resolve another batch of gh comments * resolve broken cpt state * revise testutil to use the new state * begin updating the state transition func to pass in more compartmentalized args * finish editing transition function to return errors * block operations pretty much done with refactor * state transition fully refactored * got epoch processing completed * fix build in fork choice * fixing more of the build * fix up broken sync package * it builds nowww it buildssss * revert registry changes * Recompute on Read (#4627) * compute on read * fix up eth1 data votes * looking into slashings bug introduced in core/ * able to advance more slots * add logging * can now sync with testnet yay * remove the leaves algorithm and other merkle imports * expose initialize unsafe funcs * Update beacon-chain/db/kv/state.go * lint Co-authored-by: Raul Jordan <raul@prysmaticlabs.com> * More Optimizations for New State (#4641) * map optimization * more optimizations * use a custom hasher * comment * block operations optimizations * Update beacon-chain/state/types.go Co-Authored-By: Raul Jordan <raul@prysmaticlabs.com> * fixed up various operations to use the validator index map access Co-authored-by: Raul Jordan <raul@prysmaticlabs.com> * archiver tests pass * fixing cache tests * cache tests passing * edited validator tests * powchain tests passing * halfway thru sync tests * more sync test fixes * add in tests for state/ * working through rpc tests * assignments tests passed * almost done with rpc/beacon tests * resolved painful validator test * fixed up even more tests * resolve tests * fix build * reduce a randao mixes copy * fixes under //beacon-chain/blockchain/... * build //beacon-chain/core/... * fixes * Runtime Optimizations (#4648) * parallelize shuffling * clean up * lint * fix build * use callback to read from registry * fix array roots and size map * new improvements * reduce hash allocs * improved shuffling * terence's review * use different method * raul's comment * new array roots * remove clone in pre-compute * Update beacon-chain/state/types.go Co-Authored-By: Raul Jordan <raul@prysmaticlabs.com> * raul's review * lint * fix build issues * fix visibility Co-authored-by: Raul Jordan <raul@prysmaticlabs.com> * fix visibility * build works for all * fix blockchain test * fix a few tests * fix more tests * update validator in slashing * archiver passing * fixed rpc/validator * progress on core tests * resolve broken rpc tests * blockchain tests passed * fix up some tests in core * fix message diff * remove unnecessary save * Save validator after slashing * Update validators one by one * another update * fix everything * fix more precompute tests * fix blocks tests * more elegant fix * more helper fixes * change back ? * fix test * fix skip slot * fix test * reset caches * fix testutil * raceoff fixed * passing * Retrieve cached state in the beginning * lint * Fixed tests part 1 * Fixed rest of the tests * Minor changes to avoid copying, small refactor to reduce deplicated code * Handle att req for slot 0 * New beacon state: Only populate merkle layers as needed, copy merkle layers on copy/clone. (#4689) * Only populate merkle layers as needed, copy merkle layers on copy/clone. * use custom copy * Make maps of correct size * slightly fast, doesn't wait for lock Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com> * Target root can't be 0x00 * Don't use cache for current slot (may not be the right fix) * fixed up tests * Remove some copy for init sync. Not sure if it is safe enough for runtime though... testing... * Align with prev logic for process slots cachedState.Slot() < slot * Fix Initial Sync Flag (#4692) * fixes * fix up some test failures due to lack of nil checks * fix up some test failures due to lack of nil checks * fix up imports * revert some changes * imports Co-authored-by: Raul Jordan <raul@prysmaticlabs.com> * resolving further conflicts * Better skip slot cache (#4694) * Return copy of skip slot cache state, disable skip slot cache on sync * fix * Fix pruning * fix up issues with broken tests Co-authored-by: Nishant Das <nish1993@hotmail.com> Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com> Co-authored-by: shayzluf <thezluf@gmail.com> Co-authored-by: terence tsao <terence@prysmaticlabs.com> Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
256 lines
8.7 KiB
Go
256 lines
8.7 KiB
Go
package beacon
|
|
|
|
import (
|
|
"context"
|
|
"strconv"
|
|
|
|
"github.com/pkg/errors"
|
|
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/flags"
|
|
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
|
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
|
"github.com/prysmaticlabs/prysm/shared/hashutil"
|
|
"github.com/prysmaticlabs/prysm/shared/pagination"
|
|
"github.com/prysmaticlabs/prysm/shared/params"
|
|
"google.golang.org/grpc/codes"
|
|
"google.golang.org/grpc/status"
|
|
)
|
|
|
|
// ListValidatorAssignments retrieves the validator assignments for a given epoch,
|
|
// optional validator indices or public keys may be included to filter validator assignments.
|
|
func (bs *Server) ListValidatorAssignments(
|
|
ctx context.Context, req *ethpb.ListValidatorAssignmentsRequest,
|
|
) (*ethpb.ValidatorAssignments, error) {
|
|
if int(req.PageSize) > flags.Get().MaxPageSize {
|
|
return nil, status.Errorf(
|
|
codes.InvalidArgument,
|
|
"Requested page size %d can not be greater than max size %d",
|
|
req.PageSize,
|
|
flags.Get().MaxPageSize,
|
|
)
|
|
}
|
|
|
|
var res []*ethpb.ValidatorAssignments_CommitteeAssignment
|
|
headState, err := bs.HeadFetcher.HeadState(ctx)
|
|
if err != nil {
|
|
return nil, status.Error(codes.Internal, "Could not get head state")
|
|
}
|
|
filtered := map[uint64]bool{} // track filtered validators to prevent duplication in the response.
|
|
filteredIndices := make([]uint64, 0)
|
|
requestedEpoch := helpers.CurrentEpoch(headState)
|
|
|
|
switch q := req.QueryFilter.(type) {
|
|
case *ethpb.ListValidatorAssignmentsRequest_Genesis:
|
|
if q.Genesis {
|
|
requestedEpoch = 0
|
|
}
|
|
case *ethpb.ListValidatorAssignmentsRequest_Epoch:
|
|
requestedEpoch = q.Epoch
|
|
}
|
|
|
|
if requestedEpoch > helpers.CurrentEpoch(headState) {
|
|
return nil, status.Errorf(
|
|
codes.InvalidArgument,
|
|
"Cannot retrieve information about an epoch in the future, current epoch %d, requesting %d",
|
|
helpers.CurrentEpoch(headState),
|
|
requestedEpoch,
|
|
)
|
|
}
|
|
|
|
// Filter out assignments by public keys.
|
|
for _, pubKey := range req.PublicKeys {
|
|
index, ok, err := bs.BeaconDB.ValidatorIndex(ctx, pubKey)
|
|
if err != nil {
|
|
return nil, status.Errorf(codes.Internal, "Could not retrieve validator index: %v", err)
|
|
}
|
|
if !ok {
|
|
return nil, status.Errorf(codes.NotFound, "Could not find validator index for public key %#x", pubKey)
|
|
}
|
|
filtered[index] = true
|
|
filteredIndices = append(filteredIndices, index)
|
|
}
|
|
|
|
// Filter out assignments by validator indices.
|
|
for _, index := range req.Indices {
|
|
if !filtered[index] {
|
|
filteredIndices = append(filteredIndices, index)
|
|
}
|
|
}
|
|
|
|
activeIndices, err := helpers.ActiveValidatorIndices(headState, requestedEpoch)
|
|
if err != nil {
|
|
return nil, status.Errorf(codes.Internal, "Could not retrieve active validator indices: %v", err)
|
|
}
|
|
if len(filteredIndices) == 0 {
|
|
if len(activeIndices) == 0 {
|
|
return ðpb.ValidatorAssignments{
|
|
Assignments: make([]*ethpb.ValidatorAssignments_CommitteeAssignment, 0),
|
|
TotalSize: int32(0),
|
|
NextPageToken: strconv.Itoa(0),
|
|
}, nil
|
|
}
|
|
// If no filter was specified, return assignments from active validator indices with pagination.
|
|
filteredIndices = activeIndices
|
|
}
|
|
|
|
start, end, nextPageToken, err := pagination.StartAndEndPage(req.PageToken, int(req.PageSize), len(filteredIndices))
|
|
if err != nil {
|
|
return nil, status.Errorf(codes.Internal, "Could not paginate results: %v", err)
|
|
}
|
|
|
|
shouldFetchFromArchive := requestedEpoch < bs.FinalizationFetcher.FinalizedCheckpt().Epoch
|
|
|
|
// initialize all committee related data.
|
|
committeeAssignments := map[uint64]*helpers.CommitteeAssignmentContainer{}
|
|
proposerIndexToSlot := map[uint64]uint64{}
|
|
archivedInfo := &pb.ArchivedCommitteeInfo{}
|
|
archivedBalances := []uint64{}
|
|
archivedAssignments := make(map[uint64]*ethpb.ValidatorAssignments_CommitteeAssignment)
|
|
|
|
if shouldFetchFromArchive {
|
|
archivedInfo, archivedBalances, err = bs.archivedCommitteeData(ctx, requestedEpoch)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
archivedAssignments, err = archivedValidatorCommittee(
|
|
requestedEpoch,
|
|
archivedInfo,
|
|
activeIndices,
|
|
archivedBalances,
|
|
)
|
|
if err != nil {
|
|
return nil, status.Errorf(codes.Internal, "Could not retrieve archived assignment for epoch %d: %v", requestedEpoch, err)
|
|
}
|
|
} else {
|
|
committeeAssignments, proposerIndexToSlot, err = helpers.CommitteeAssignments(headState, requestedEpoch)
|
|
if err != nil {
|
|
return nil, status.Errorf(codes.Internal, "Could not compute committee assignments: %v", err)
|
|
}
|
|
}
|
|
|
|
for _, index := range filteredIndices[start:end] {
|
|
if int(index) >= headState.NumValidators() {
|
|
return nil, status.Errorf(codes.OutOfRange, "Validator index %d >= validator count %d",
|
|
index, headState.NumValidators())
|
|
}
|
|
if shouldFetchFromArchive {
|
|
assignment, ok := archivedAssignments[index]
|
|
if !ok {
|
|
return nil, status.Errorf(codes.Internal, "Could not get archived committee assignment for index %d", index)
|
|
}
|
|
pubkey := headState.PubkeyAtIndex(index)
|
|
assignment.PublicKey = pubkey[:]
|
|
res = append(res, assignment)
|
|
continue
|
|
}
|
|
comAssignment := committeeAssignments[index]
|
|
pubkey := headState.PubkeyAtIndex(index)
|
|
assign := ðpb.ValidatorAssignments_CommitteeAssignment{
|
|
BeaconCommittees: comAssignment.Committee,
|
|
CommitteeIndex: comAssignment.CommitteeIndex,
|
|
AttesterSlot: comAssignment.AttesterSlot,
|
|
ProposerSlot: proposerIndexToSlot[index],
|
|
PublicKey: pubkey[:],
|
|
}
|
|
res = append(res, assign)
|
|
}
|
|
|
|
return ðpb.ValidatorAssignments{
|
|
Epoch: requestedEpoch,
|
|
Assignments: res,
|
|
NextPageToken: nextPageToken,
|
|
TotalSize: int32(len(filteredIndices)),
|
|
}, nil
|
|
}
|
|
|
|
// Computes validator assignments for an epoch and validator index using archived committee
|
|
// information, archived balances, and a set of active validators.
|
|
func archivedValidatorCommittee(
|
|
epoch uint64,
|
|
archivedInfo *pb.ArchivedCommitteeInfo,
|
|
activeIndices []uint64,
|
|
archivedBalances []uint64,
|
|
) (map[uint64]*ethpb.ValidatorAssignments_CommitteeAssignment, error) {
|
|
proposerSeed := bytesutil.ToBytes32(archivedInfo.ProposerSeed)
|
|
attesterSeed := bytesutil.ToBytes32(archivedInfo.AttesterSeed)
|
|
|
|
startSlot := helpers.StartSlot(epoch)
|
|
proposerIndexToSlot := make(map[uint64]uint64)
|
|
activeVals := make([]*ethpb.Validator, len(archivedBalances))
|
|
for i, bal := range archivedBalances {
|
|
activeVals[i] = ðpb.Validator{EffectiveBalance: bal}
|
|
}
|
|
|
|
for slot := startSlot; slot < startSlot+params.BeaconConfig().SlotsPerEpoch; slot++ {
|
|
seedWithSlot := append(proposerSeed[:], bytesutil.Bytes8(slot)...)
|
|
seedWithSlotHash := hashutil.Hash(seedWithSlot)
|
|
i, err := helpers.ComputeProposerIndex(activeVals, activeIndices, seedWithSlotHash)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "could not check proposer at slot %d", slot)
|
|
}
|
|
proposerIndexToSlot[i] = slot
|
|
}
|
|
|
|
assignmentMap := make(map[uint64]*ethpb.ValidatorAssignments_CommitteeAssignment)
|
|
for slot := startSlot; slot < startSlot+params.BeaconConfig().SlotsPerEpoch; slot++ {
|
|
var countAtSlot = uint64(len(activeIndices)) / params.BeaconConfig().SlotsPerEpoch / params.BeaconConfig().TargetCommitteeSize
|
|
if countAtSlot > params.BeaconConfig().MaxCommitteesPerSlot {
|
|
countAtSlot = params.BeaconConfig().MaxCommitteesPerSlot
|
|
}
|
|
if countAtSlot == 0 {
|
|
countAtSlot = 1
|
|
}
|
|
for i := uint64(0); i < countAtSlot; i++ {
|
|
committee, err := helpers.BeaconCommittee(activeIndices, attesterSeed, slot, i)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not compute committee")
|
|
}
|
|
for _, index := range committee {
|
|
assignmentMap[index] = ðpb.ValidatorAssignments_CommitteeAssignment{
|
|
BeaconCommittees: committee,
|
|
CommitteeIndex: i,
|
|
AttesterSlot: slot,
|
|
ProposerSlot: proposerIndexToSlot[index],
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return assignmentMap, nil
|
|
}
|
|
|
|
func (bs *Server) archivedCommitteeData(ctx context.Context, requestedEpoch uint64) (*pb.ArchivedCommitteeInfo,
|
|
[]uint64, error) {
|
|
archivedInfo, err := bs.BeaconDB.ArchivedCommitteeInfo(ctx, requestedEpoch)
|
|
if err != nil {
|
|
return nil, nil, status.Errorf(
|
|
codes.Internal,
|
|
"Could not retrieve archived committee info for epoch %d",
|
|
requestedEpoch,
|
|
)
|
|
}
|
|
if archivedInfo == nil {
|
|
return nil, nil, status.Errorf(
|
|
codes.NotFound,
|
|
"Could not retrieve data for epoch %d, perhaps --archive in the running beacon node is disabled",
|
|
requestedEpoch,
|
|
)
|
|
}
|
|
archivedBalances, err := bs.BeaconDB.ArchivedBalances(ctx, requestedEpoch)
|
|
if err != nil {
|
|
return nil, nil, status.Errorf(
|
|
codes.Internal,
|
|
"Could not retrieve archived balances for epoch %d",
|
|
requestedEpoch,
|
|
)
|
|
}
|
|
if archivedBalances == nil {
|
|
return nil, nil, status.Errorf(
|
|
codes.NotFound,
|
|
"Could not retrieve data for epoch %d, perhaps --archive in the running beacon node is disabled",
|
|
requestedEpoch,
|
|
)
|
|
}
|
|
return archivedInfo, archivedBalances, nil
|
|
}
|