---
# System prepended metadata

title: Prysm - analise of code

---

# Prysm - analise of code
## VALIDATOR

#### validator/client/validator.go:61
````go
type validator struct {
	logValidatorBalances               bool
	useWeb                             bool
	emitAccountMetrics                 bool
	logDutyCountDown                   bool
	domainDataLock                     sync.Mutex
	attLogsLock                        sync.Mutex
	aggregatedSlotCommitteeIDCacheLock sync.Mutex
	prevBalanceLock                    sync.RWMutex
	slashableKeysLock                  sync.RWMutex
	eipImportBlacklistedPublicKeys     map[[fieldparams.BLSPubkeyLength]byte]bool
	walletInitializedFeed              *event.Feed
	attLogs                            map[[32]byte]*attSubmitted
	startBalances                      map[[fieldparams.BLSPubkeyLength]byte]uint64
	duties                             *ethpb.DutiesResponse
	/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        type DutiesResponse struct {
            state              protoimpl.MessageState
            sizeCache          protoimpl.SizeCache
            unknownFields      protoimpl.UnknownFields
            Duties             []*DutiesResponse_Duty `protobuf:"bytes,1,rep,name=duties,proto3" json:"duties,omitempty"`
            CurrentEpochDuties []*DutiesResponse_Duty `protobuf:"bytes,2,rep,name=current_epoch_duties,json=currentEpochDuties,proto3" json:"current_epoch_duties,omitempty"`
            NextEpochDuties    []*DutiesResponse_Duty `protobuf:"bytes,3,rep,name=next_epoch_duties,json=nextEpochDuties,proto3" json:"next_epoch_duties,omitempty"`
        }
	
            type DutiesResponse_Duty struct {
                state           protoimpl.MessageState
                sizeCache       protoimpl.SizeCache
                unknownFields   protoimpl.UnknownFields
                Committee       []types.ValidatorIndex `protobuf:"varint,1,rep,packed,name=committee,proto3" json:"committee,omitempty" cast-type:"github.com/prysmaticlabs/eth2-types.ValidatorIndex"`
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                CommitteeIndex  types.CommitteeIndex   `protobuf:"varint,2,opt,name=committee_index,json=committeeIndex,proto3" json:"committee_index,omitempty" cast-type:"github.com/prysmaticlabs/eth2-types.CommitteeIndex"`
                AttesterSlot    types.Slot             `protobuf:"varint,3,opt,name=attester_slot,json=attesterSlot,proto3" json:"attester_slot,omitempty" cast-type:"github.com/prysmaticlabs/eth2-types.Slot"`
                ProposerSlots   []types.Slot           `protobuf:"varint,4,rep,packed,name=proposer_slots,json=proposerSlots,proto3" json:"proposer_slots,omitempty" cast-type:"github.com/prysmaticlabs/eth2-types.Slot"`
                PublicKey       []byte                 `protobuf:"bytes,5,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty" ssz-size:"48"`
                Status          ValidatorStatus        `protobuf:"varint,6,opt,name=status,proto3,enum=ethereum.eth.v1alpha1.ValidatorStatus" json:"status,omitempty"`
                    const ( ^^^^^^^^^^^^^^^^^^^^^
                        ValidatorStatus_UNKNOWN_STATUS      ValidatorStatus = 0
                        ValidatorStatus_DEPOSITED           ValidatorStatus = 1
                        ValidatorStatus_PENDING             ValidatorStatus = 2
                        ValidatorStatus_ACTIVE              ValidatorStatus = 3
                        ValidatorStatus_EXITING             ValidatorStatus = 4
                        ValidatorStatus_SLASHING            ValidatorStatus = 5
                        ValidatorStatus_EXITED              ValidatorStatus = 6
                        ValidatorStatus_INVALID             ValidatorStatus = 7
                        ValidatorStatus_PARTIALLY_DEPOSITED ValidatorStatus = 8
                    )

		            ValidatorIndex  types.ValidatorIndex   `protobuf:"varint,7,opt,name=validator_index,json=validatorIndex,proto3" json:"validator_index,omitempty" cast-type:"github.com/prysmaticlabs/eth2-types.ValidatorIndex"`
                IsSyncCommittee bool                                                 `protobuf:"varint,8,opt,name=is_sync_committee,json=isSyncCommittee,proto3" json:"is_sync_committee,omitempty"`
            }
	 */
	prevBalance                        map[[fieldparams.BLSPubkeyLength]byte]uint64
	pubkeyToValidatorIndex             map[[fieldparams.BLSPubkeyLength]byte]types.ValidatorIndex
	graffitiOrderedIndex               uint64
	aggregatedSlotCommitteeIDCache     *lru.Cache
	domainDataCache                    *ristretto.Cache
	highestValidSlot                   types.Slot
	genesisTime                        uint64
	blockFeed                          *event.Feed
	interopKeysConfig                  *local.InteropKeymanagerConfig
	wallet                             *wallet.Wallet
	graffitiStruct                     *graffiti.Graffiti
	node                               ethpb.NodeClient
	/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            type NodeClient interface {
                GetSyncStatus(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*SyncStatus, error)
                GetGenesis(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*Genesis, error)
                GetVersion(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*Version, error)
                ListImplementedServices(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*ImplementedServices, error)
                GetHost(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*HostData, error)
                GetPeer(ctx context.Context, in *PeerRequest, opts ...grpc.CallOption) (*Peer, error)
                ListPeers(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*Peers, error)
                GetETH1ConnectionStatus(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*ETH1ConnectionStatus, error)
            }
	 */
	slashingProtectionClient           ethpb.SlasherClient
	db                                 vdb.Database
	beaconClient                       ethpb.BeaconChainClient
	/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        type BeaconChainClient interface {
            ListAttestations(ctx context.Context, in *ListAttestationsRequest, opts ...grpc.CallOption) (*ListAttestationsResponse, error)
            ListIndexedAttestations(ctx context.Context, in *ListIndexedAttestationsRequest, opts ...grpc.CallOption) (*ListIndexedAttestationsResponse, error)
            StreamAttestations(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (BeaconChain_StreamAttestationsClient, error)
            StreamIndexedAttestations(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (BeaconChain_StreamIndexedAttestationsClient, error)
            AttestationPool(ctx context.Context, in *AttestationPoolRequest, opts ...grpc.CallOption) (*AttestationPoolResponse, error)
            ListBlocks(ctx context.Context, in *ListBlocksRequest, opts ...grpc.CallOption) (*ListBlocksResponse, error)
            ListBeaconBlocks(ctx context.Context, in *ListBlocksRequest, opts ...grpc.CallOption) (*ListBeaconBlocksResponse, error)
            StreamBlocks(ctx context.Context, in *StreamBlocksRequest, opts ...grpc.CallOption) (BeaconChain_StreamBlocksClient, error)
            StreamChainHead(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (BeaconChain_StreamChainHeadClient, error)
            GetChainHead(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*ChainHead, error)
            ListBeaconCommittees(ctx context.Context, in *ListCommitteesRequest, opts ...grpc.CallOption) (*BeaconCommittees, error)
            ListValidatorBalances(ctx context.Context, in *ListValidatorBalancesRequest, opts ...grpc.CallOption) (*ValidatorBalances, error)
            ListValidators(ctx context.Context, in *ListValidatorsRequest, opts ...grpc.CallOption) (*Validators, error)
            GetValidator(ctx context.Context, in *GetValidatorRequest, opts ...grpc.CallOption) (*Validator, error)
            GetValidatorActiveSetChanges(ctx context.Context, in *GetValidatorActiveSetChangesRequest, opts ...grpc.CallOption) (*ActiveSetChanges, error)
            GetValidatorQueue(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*ValidatorQueue, error)
            GetValidatorPerformance(ctx context.Context, in *ValidatorPerformanceRequest, opts ...grpc.CallOption) (*ValidatorPerformanceResponse, error)
            ListValidatorAssignments(ctx context.Context, in *ListValidatorAssignmentsRequest, opts ...grpc.CallOption) (*ValidatorAssignments, error)
            GetValidatorParticipation(ctx context.Context, in *GetValidatorParticipationRequest, opts ...grpc.CallOption) (*ValidatorParticipationResponse, error)
            GetBeaconConfig(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*BeaconConfig, error)
            StreamValidatorsInfo(ctx context.Context, opts ...grpc.CallOption) (BeaconChain_StreamValidatorsInfoClient, error)
            SubmitAttesterSlashing(ctx context.Context, in *AttesterSlashing, opts ...grpc.CallOption) (*SubmitSlashingResponse, error)
            SubmitProposerSlashing(ctx context.Context, in *ProposerSlashing, opts ...grpc.CallOption) (*SubmitSlashingResponse, error)
            GetIndividualVotes(ctx context.Context, in *IndividualVotesRequest, opts ...grpc.CallOption) (*IndividualVotesRespond, error)
        }
	 */
	keyManager                         keymanager.IKeymanager
	ticker                             slots.Ticker
	validatorClient                    ethpb.BeaconNodeValidatorClient
	/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
	proto/prysm/v1alpha1/validator.pb.go:4020
        type BeaconNodeValidatorClient interface {
            GetDuties(ctx context.Context, in *DutiesRequest, opts ...grpc.CallOption) (*DutiesResponse, error)
            StreamDuties(ctx context.Context, in *DutiesRequest, opts ...grpc.CallOption) (BeaconNodeValidator_StreamDutiesClient, error)
            DomainData(ctx context.Context, in *DomainRequest, opts ...grpc.CallOption) (*DomainResponse, error)
            // Deprecated: Do not use.
            WaitForChainStart(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (BeaconNodeValidator_WaitForChainStartClient, error)
            WaitForActivation(ctx context.Context, in *ValidatorActivationRequest, opts ...grpc.CallOption) (BeaconNodeValidator_WaitForActivationClient, error)
            ValidatorIndex(ctx context.Context, in *ValidatorIndexRequest, opts ...grpc.CallOption) (*ValidatorIndexResponse, error)
            ValidatorStatus(ctx context.Context, in *ValidatorStatusRequest, opts ...grpc.CallOption) (*ValidatorStatusResponse, error)
            MultipleValidatorStatus(ctx context.Context, in *MultipleValidatorStatusRequest, opts ...grpc.CallOption) (*MultipleValidatorStatusResponse, error)
            // Deprecated: Do not use.
            GetBlock(ctx context.Context, in *BlockRequest, opts ...grpc.CallOption) (*BeaconBlock, error)
            // Deprecated: Do not use.
            ProposeBlock(ctx context.Context, in *SignedBeaconBlock, opts ...grpc.CallOption) (*ProposeResponse, error)
            GetBeaconBlock(ctx context.Context, in *BlockRequest, opts ...grpc.CallOption) (*GenericBeaconBlock, error)
            ProposeBeaconBlock(ctx context.Context, in *GenericSignedBeaconBlock, opts ...grpc.CallOption) (*ProposeResponse, error)
            PrepareBeaconProposer(ctx context.Context, in *PrepareBeaconProposerRequest, opts ...grpc.CallOption) (*empty.Empty, error)
            GetAttestationData(ctx context.Context, in *AttestationDataRequest, opts ...grpc.CallOption) (*AttestationData, error)
            ProposeAttestation(ctx context.Context, in *Attestation, opts ...grpc.CallOption) (*AttestResponse, error)
            SubmitAggregateSelectionProof(ctx context.Context, in *AggregateSelectionRequest, opts ...grpc.CallOption) (*AggregateSelectionResponse, error)
            SubmitSignedAggregateSelectionProof(ctx context.Context, in *SignedAggregateSubmitRequest, opts ...grpc.CallOption) (*SignedAggregateSubmitResponse, error)
            ProposeExit(ctx context.Context, in *SignedVoluntaryExit, opts ...grpc.CallOption) (*ProposeExitResponse, error)
            SubscribeCommitteeSubnets(ctx context.Context, in *CommitteeSubnetsSubscribeRequest, opts ...grpc.CallOption) (*empty.Empty, error)
            CheckDoppelGanger(ctx context.Context, in *DoppelGangerRequest, opts ...grpc.CallOption) (*DoppelGangerResponse, error)
            GetSyncMessageBlockRoot(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*SyncMessageBlockRootResponse, error)
            SubmitSyncMessage(ctx context.Context, in *SyncCommitteeMessage, opts ...grpc.CallOption) (*empty.Empty, error)
            GetSyncSubcommitteeIndex(ctx context.Context, in *SyncSubcommitteeIndexRequest, opts ...grpc.CallOption) (*SyncSubcommitteeIndexResponse, error)
            GetSyncCommitteeContribution(ctx context.Context, in *SyncCommitteeContributionRequest, opts ...grpc.CallOption) (*SyncCommitteeContribution, error)
            SubmitSignedContributionAndProof(ctx context.Context, in *SignedContributionAndProof, opts ...grpc.CallOption) (*empty.Empty, error)
            StreamBlocksAltair(ctx context.Context, in *StreamBlocksRequest, opts ...grpc.CallOption) (BeaconNodeValidator_StreamBlocksAltairClient, error)
        }

	*/
	graffiti                           []byte
	voteStats                          voteStats
	Web3SignerConfig                   *remote_web3signer.SetupConfig
	feeRecipientConfig                 *validator_service_config.FeeRecipientConfig
	walletIntializedChannel            chan *wallet.Wallet
}
````

````go
type DutiesResponse struct {
	state         protoimpl.MessageState
	sizeCache     protoimpl.SizeCache
	unknownFields protoimpl.UnknownFields

	// Deprecated: Do not use.
	Duties             []*DutiesResponse_Duty `protobuf:"bytes,1,rep,name=duties,proto3" json:"duties,omitempty"`
	CurrentEpochDuties []*DutiesResponse_Duty `protobuf:"bytes,2,rep,name=current_epoch_duties,json=currentEpochDuties,proto3" json:"current_epoch_duties,omitempty"`
	^^^^^^^^^^^^^^^^^^
	NextEpochDuties    []*DutiesResponse_Duty `protobuf:"bytes,3,rep,name=next_epoch_duties,json=nextEpochDuties,proto3" json:"next_epoch_duties,omitempty"`
	^^^^^^^^^^^^^^^^^^^
}
````

#### UpdateDuties получение валидатором заданий по комитетам
validator/client/validator.go:546
````go
// UpdateDuties checks the slot number to determine if the validator's
// list of upcoming assignments needs to be updated. For example, at the
// beginning of a new epoch.
func (v *validator) UpdateDuties(ctx context.Context, slot types.Slot) error {
	...
	resp, err := v.validatorClient.GetDuties(ctx, req)
}
````


### ROLES 
validator/client/iface/validator.go:17
````go
// ValidatorRole defines the validator role.
type ValidatorRole int8

const (
	// RoleUnknown means that the role of the validator cannot be determined.
	RoleUnknown ValidatorRole = iota
	// RoleAttester means that the validator should submit an attestation.
	RoleAttester
	// RoleProposer means that the validator should propose a block.
	RoleProposer
	// RoleAggregator means that the validator should submit an aggregation and proof.
	RoleAggregator
	// RoleSyncCommittee means that the validator should submit a sync committee message.
	RoleSyncCommittee
	// RoleSyncCommitteeAggregator means the valiator should aggregate sync committee messages and submit a sync committee contribution.
	RoleSyncCommitteeAggregator
)
````

### Определение ролей 
validator/client/validator.go:676
````go
// RolesAt slot returns the validator roles at the given slot. Returns nil if the
// validator is known to not have a roles at the slot. Returns UNKNOWN if the
// validator assignments are unknown. Otherwise returns a valid ValidatorRole map.
func (v *validator) RolesAt(ctx context.Context, slot types.Slot) (map[[fieldparams.BLSPubkeyLength]byte][]iface.ValidatorRole, error) {
    rolesAt := make(map[[fieldparams.BLSPubkeyLength]byte][]iface.ValidatorRole)
	for validator, duty := range v.duties.Duties {
		...
		rolesAt[pubKey] = roles
	}
}
````


### Основной процесс валидатора run
validator/client/runner.go:35

 ````go
 // Run the main validator routine. This routine exits if the context is
// canceled.
//
// Order of operations:
// 1 - Initialize validator data
// 2 - Wait for validator activation
// 3 - Wait for the next slot start
// 4 - Update assignments
// 5 - Determine role at current slot
// 6 - Perform assigned role, if any
func run(ctx context.Context, v iface.Validator) {
    ...
	case slot := <-v.NextSlot():   // v.ticker.C()
	/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
	func (v *validator) WaitForChainStart(ctx context.Context) error
	    // Once the ChainStart log is received, we update the genesis time of the validator client
		// and begin a slot ticker used to track the current slot the beacon node is in.
		v.ticker = slots.NewSlotTicker(time.Unix(int64(v.genesisTime), 0), params.BeaconConfig().SecondsPerSlot)
	*/
        ...
        if err := v.UpdateDuties(ctx, headSlot); err != nil {
            handleAssignmentError(err, headSlot)
        }

        // Start fetching domain data for the next epoch.
        if slots.IsEpochEnd(slot) {
            go v.UpdateDomainDataCaches(ctx, slot+1)
        }
        ...
        allRoles, err := v.RolesAt(ctx, slot)
        // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ get current roles of validator
        if err != nil {
        log.WithError(err).Error("Could not get validator roles")
        span.End()
        continue
        }
        for pubKey, roles := range allRoles {
            go func(role iface.ValidatorRole, pubKey [fieldparams.BLSPubkeyLength]byte) {
            defer wg.Done()
            switch role {
            case iface.RoleAttester:
            v.SubmitAttestation(slotCtx, slot, pubKey)
            case iface.RoleProposer:
            v.ProposeBlock(slotCtx, slot, pubKey)
            case iface.RoleAggregator:
            v.SubmitAggregateAndProof(slotCtx, slot, pubKey)
            case iface.RoleSyncCommittee:
            v.SubmitSyncCommitteeMessage(slotCtx, slot, pubKey)
            case iface.RoleSyncCommitteeAggregator:
            v.SubmitSignedContributionAndProof(slotCtx, slot, pubKey)
            case iface.RoleUnknown:
            log.WithField("pubKey", fmt.Sprintf("%#x", bytesutil.Trunc(pubKey[:]))).Trace("No active roles, doing nothing")
            default:
            log.Warnf("Unhandled role %v", role)
            }
            }(role, pubKey)
        }
		...
}
 ````






## BEACON

###  CommitteeAssignments 
реализация самой логики
beacon-chain/core/helpers/beacon_committee.go:149
````go
// CommitteeAssignments is a map of validator indices pointing to the appropriate committee
// assignment for the given epoch.
//
// 1. Determine the proposer validator index for each slot.
// 2. Compute all committees.
// 3. Determine the attesting slot for each committee.
// 4. Construct a map of validator indices pointing to the respective committees.
func CommitteeAssignments(
ctx context.Context,
state state.BeaconState,
epoch types.Epoch,
) (map[types.ValidatorIndex]*CommitteeAssignmentContainer, map[types.ValidatorIndex][]types.Slot, error) {
    ....
    return validatorIndexToCommittee, proposerIndexToSlots, nil
}
````
### Назначение комитета
beacon-chain/rpc/prysm/v1alpha1/validator/assignments.go:110
````go
// Compute the validator duties from the head state's corresponding epoch
// for validators public key / indices requested.
func (vs *Server) duties(ctx context.Context, req *ethpb.DutiesRequest) (*ethpb.DutiesResponse, error) {
    ...
    committeeAssignments, proposerIndexToSlots, err := helpers.CommitteeAssignments(ctx, s, req.Epoch)
    ...	
    // Query the next epoch assignments for committee subnet subscriptions.
    nextCommitteeAssignments, nextProposerIndexToSlots, err := helpers.CommitteeAssignments(ctx, s, req.Epoch+1)
    ...
    return &ethpb.DutiesResponse{
    Duties:             validatorAssignments,
    CurrentEpochDuties: validatorAssignments,
    NextEpochDuties:    nextValidatorAssignments,
    }, nil
}
````



### New Slot
beacon-chain/blockchain/new_slot.go:32

````go
// NewSlot mimics the implementation of `on_tick` in fork choice consensus spec.
// It resets the proposer boost root in fork choice, and it updates store's justified checkpoint
// if a better checkpoint on the store's finalized checkpoint chain.
// This should only be called at the start of every slot interval.
func (s *Service) NewSlot(ctx context.Context, slot types.Slot) error {
	...
    if !slots.IsEpochStart(slot) {
		return nil
	}
	...
}
````





## SLOT/EPOCHE
что-то типа хелперов
time/slots/slottime.go:109
````go
// IsEpochStart returns true if the given slot number is an epoch starting slot
// number.
func IsEpochStart(slot types.Slot) bool {
	return slot%params.BeaconConfig().SlotsPerEpoch == 0
}

// IsEpochEnd returns true if the given slot number is an epoch ending slot
// number.
func IsEpochEnd(slot types.Slot) bool {
	return IsEpochStart(slot + 1)
}
````





## INTEGRATION 

validator/client/propose.go:41
````go
// ProposeBlock proposes a new beacon block for a given slot. This method collects the
// previous beacon block, any pending deposits, and ETH1 data from the beacon
// chain node to construct the new block. The new block is then processed with
// the state root computation, and finally signed by the validator before being
// sent back to the beacon node for broadcasting.
func (v *validator) ProposeBlock(ctx context.Context, slot types.Slot, pubKey [fieldparams.BLSPubkeyLength]byte) {
	...
	// TODO в стеке запрос АПИ GetCandidates 
	// Request block from beacon node
	b, err := v.validatorClient.GetBeaconBlock(ctx, &ethpb.BlockRequest{
		Slot:         slot,
		RandaoReveal: randaoReveal,
		Graffiti:     g,
	})
	...
	// Sign returned block from beacon node
	wb, err := wrapper.WrappedBeaconBlock(b.Block)
	...
	sig, signingRoot, err := v.signBlock(ctx, pubKey, epoch, slot, wb)
	...
	blk, err := wrapper.BuildSignedBeaconBlock(wb, sig)
	...
	// Propose and broadcast block via beacon node
	proposal, err := blk.PbGenericBlock()
	...
	blkResp, err := v.validatorClient.ProposeBeaconBlock(ctx, proposal)
	...
	// TODO вместо логики Bellatrix - вызов финализации и создания блока на GWAT
	// todo перепроверить
	if blk.Version() == version.Bellatrix {
		p, err := blk.Block().Body().ExecutionPayload()
		if err != nil {
			log.WithError(err).Error("Failed to get execution payload")
			return
		}
		log = log.WithField("payloadHash", fmt.Sprintf("%#x", bytesutil.Trunc(p.BlockHash)))
		log = log.WithField("txCount", len(p.Transactions))
	}

	blkRoot := fmt.Sprintf("%#x", bytesutil.Trunc(blkResp.BlockRoot))
	log.WithFields(logrus.Fields{
		"slot":            blk.Block().Slot(),
		"blockRoot":       blkRoot,
		"numAttestations": len(blk.Block().Body().Attestations()),
		"numDeposits":     len(blk.Block().Body().Deposits()),
		"graffiti":        string(blk.Block().Body().Graffiti()),
		"fork":            version.String(blk.Block().Version()),
	}).Info("Submitted new block")
	...
}

````

beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go:37
````go
// GetBeaconBlock is called by a proposer during its assigned slot to request a block to sign
// by passing in the slot and the signed randao reveal of the slot. Returns phase0 beacon blocks
// before the Altair fork epoch and Altair blocks post-fork epoch.
func (vs *Server) GetBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) (*ethpb.GenericBeaconBlock, error) {
	ctx, span := trace.StartSpan(ctx, "ProposerServer.GetBeaconBlock")
	defer span.End()
	span.AddAttributes(trace.Int64Attribute("slot", int64(req.Slot)))
	if slots.ToEpoch(req.Slot) < params.BeaconConfig().AltairForkEpoch {
		blk, err := vs.getPhase0BeaconBlock(ctx, req)
		if err != nil {
			return nil, status.Errorf(codes.Internal, "Could not fetch phase0 beacon block: %v", err)
		}
		return &ethpb.GenericBeaconBlock{Block: &ethpb.GenericBeaconBlock_Phase0{Phase0: blk}}, nil
	} else if slots.ToEpoch(req.Slot) < params.BeaconConfig().BellatrixForkEpoch {
		blk, err := vs.getAltairBeaconBlock(ctx, req)
		//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
		if err != nil {
			return nil, status.Errorf(codes.Internal, "Could not fetch Altair beacon block: %v", err)
		}
		return &ethpb.GenericBeaconBlock{Block: &ethpb.GenericBeaconBlock_Altair{Altair: blk}}, nil
	}

	// An optimistic validator MUST NOT produce a block (i.e., sign across the DOMAIN_BEACON_PROPOSER domain).
	if err := vs.optimisticStatus(ctx); err != nil {
		return nil, err
	}

	blk, err := vs.getBellatrixBeaconBlock(ctx, req)
	if err != nil {
		return nil, status.Errorf(codes.Internal, "Could not fetch Bellatrix beacon block: %v", err)
	}

	return &ethpb.GenericBeaconBlock{Block: &ethpb.GenericBeaconBlock_Bellatrix{Bellatrix: blk}}, nil
}
````


beacon-chain/rpc/prysm/v1alpha1/validator/proposer_altair.go:55
````go
func (vs *Server) getAltairBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) (*ethpb.BeaconBlockAltair, error) {
	ctx, span := trace.StartSpan(ctx, "ProposerServer.getAltairBeaconBlock")
	defer span.End()
	blk, err := vs.buildAltairBeaconBlock(ctx, req)
	//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
	if err != nil {
		return nil, fmt.Errorf("could not build block data: %v", err)
	}
	// Compute state root with the newly constructed block.
	wsb, err := wrapper.WrappedSignedBeaconBlock(
		&ethpb.SignedBeaconBlockAltair{Block: blk, Signature: make([]byte, 96)},
	)
	if err != nil {
		return nil, err
	}
	stateRoot, err := vs.computeStateRoot(ctx, wsb)
	if err != nil {
		interop.WriteBlockToDisk(wsb, true /*failed*/)
		return nil, fmt.Errorf("could not compute state root: %v", err)
	}
	blk.StateRoot = stateRoot
	return blk, nil
}
````


beacon-chain/rpc/prysm/v1alpha1/validator/proposer_altair.go:18
````go
func (vs *Server) buildAltairBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) (*ethpb.BeaconBlockAltair, error) {
	...
	blkData, err := vs.buildPhase0BlockData(ctx, req)
	//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
	...

	return &ethpb.BeaconBlockAltair{
		Slot:          req.Slot,
		ParentRoot:    blkData.ParentRoot,
		StateRoot:     stateRoot,
		ProposerIndex: blkData.ProposerIdx,
		Body: &ethpb.BeaconBlockBodyAltair{
			Eth1Data:          blkData.Eth1Data,
			//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
			Deposits:          blkData.Deposits,
			Attestations:      blkData.Attestations,
			RandaoReveal:      req.RandaoReveal,
			ProposerSlashings: blkData.ProposerSlashings,
			AttesterSlashings: blkData.AttesterSlashings,
			VoluntaryExits:    blkData.VoluntaryExits,
			Graffiti:          blkData.Graffiti[:],
			SyncAggregate:     syncAggregate,
		},
	}, nil
}
````


beacon-chain/rpc/prysm/v1alpha1/validator/proposer_phase0.go:77
````go
// Build data required for creating a new beacon block, so this method can be shared across forks.
func (vs *Server) buildPhase0BlockData(ctx context.Context, req *ethpb.BlockRequest) (*blockData, error) {
	...
	//NOTE: проверка синхронизации ноды
	if vs.SyncChecker.Syncing() {
		return nil, fmt.Errorf("syncing to latest head, not ready to respond")
	}
	...
	eth1Data, err := vs.eth1DataMajorityVote(ctx, head)
	...
	return &blockData{
		ParentRoot:        parentRoot,
		Graffiti:          graffiti,
		ProposerIdx:       idx,
		Eth1Data:          eth1Data,
		//^^^^^^^^^^^^^^^^^^^^^^^^^^^
		Deposits:          deposits,
		Attestations:      atts,
		ProposerSlashings: validProposerSlashings,
		AttesterSlashings: validAttSlashings,
		VoluntaryExits:    validExits,
	}, nil
}
````


beacon-chain/rpc/prysm/v1alpha1/validator/proposer_eth1data.go:33
````go
// eth1DataMajorityVote determines the appropriate eth1data for a block proposal using
// an algorithm called Voting with the Majority. The algorithm works as follows:
//  - Determine the timestamp for the start slot for the eth1 voting period.
//  - Determine the earliest and latest timestamps that a valid block can have.
//  - Determine the first block not before the earliest timestamp. This block is the lower bound.
//  - Determine the last block not after the latest timestamp. This block is the upper bound.
//  - If the last block is too early, use current eth1data from the beacon state.
//  - Filter out votes on unknown blocks and blocks which are outside of the range determined by the lower and upper bounds.
//  - If no blocks are left after filtering votes, use eth1data from the latest valid block.
//  - Otherwise:
//    - Determine the vote with the highest count. Prefer the vote with the highest eth1 block height in the event of a tie.
//    - This vote's block is the eth1 block to use for the block proposal.
func (vs *Server) eth1DataMajorityVote(ctx context.Context, beaconState state.BeaconState) (*ethpb.Eth1Data, error) {
	...
	if lastBlockDepositCount >= vs.HeadFetcher.HeadETH1Data().DepositCount {
		// TODO запрос АПИ GetCandidates 
		hash, err := vs.Eth1BlockFetcher.BlockHashByHeight(ctx, lastBlockByLatestValidTime.Number)
		//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
		if err != nil {
			log.WithError(err).Error("Could not get hash of last block by latest valid time")
			return vs.randomETH1DataVote(ctx)
		}
		return &ethpb.Eth1Data{
			BlockHash:    hash.Bytes(),
			//^^^^^^^^^^^^^^^^^^^^^^^^
			DepositCount: lastBlockDepositCount,
			DepositRoot:  lastBlockDepositRoot[:],
		}, nil
	}
	return vs.HeadFetcher.HeadETH1Data(), nil
}
````



````go

````