# 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 ðpb.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, ðpb.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 ðpb.GenericBeaconBlock{Block: ðpb.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 ðpb.GenericBeaconBlock{Block: ðpb.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 ðpb.GenericBeaconBlock{Block: ðpb.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(
ðpb.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 ðpb.BeaconBlockAltair{
Slot: req.Slot,
ParentRoot: blkData.ParentRoot,
StateRoot: stateRoot,
ProposerIndex: blkData.ProposerIdx,
Body: ðpb.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 ðpb.Eth1Data{
BlockHash: hash.Bytes(),
//^^^^^^^^^^^^^^^^^^^^^^^^
DepositCount: lastBlockDepositCount,
DepositRoot: lastBlockDepositRoot[:],
}, nil
}
return vs.HeadFetcher.HeadETH1Data(), nil
}
````
````go
````