Part 3: Annotated Specification


Beacon operations

The following are the various protocol messages that can be transmitted in a block` on the beacon chain.

For most of these, the proposer is rewarded either explicitly or implicitly for including the object in a block.

The proposer receives explicit in-protocol rewards for including the following in blocks:

  • ProposerSlashings,
  • AttesterSlashings,
  • Attestations, and
  • SyncAggregates.

Including Deposit objects in blocks is only implicitly rewarded, in that, if there are pending deposits that the block proposer does not include then the block is invalid, so the proposer receives no reward.

There is no direct reward for including VoluntaryExit objects. However, for each validator exited, rewards for the remaining validators increase very slightly, so it's as well for proposers not to ignore VoluntaryExits.


class ProposerSlashing(Container):
    signed_header_1: SignedBeaconBlockHeader
    signed_header_2: SignedBeaconBlockHeader

ProposerSlashings may be included in blocks to prove that a validator has broken the rules and ought to be slashed. Proposers receive a reward for correctly submitting these.

In this case, the rule is that a validator may not propose two different blocks at the same height, and the payload is the signed headers of the two blocks that evidence the crime. The signatures on the SignedBeaconBlockHeaders are checked to verify that they were both signed by the accused validator.


class AttesterSlashing(Container):
    attestation_1: IndexedAttestation
    attestation_2: IndexedAttestation

AttesterSlashings may be included in blocks to prove that one or more validators in a committee has broken the rules and ought to be slashed. Proposers receive a reward for correctly submitting these.

The contents of the IndexedAttestations are checked against the attester slashing conditions in is_slashable_attestation_data(). If there is a violation, then any validator that attested to both attestation_1 and attestation_2 is slashed, see process_attester_slashing().

AttesterSlashings can be very large since they could in principle list the indices of all the validators in a committee. However, in contrast to proposer slashings, many validators can be slashed as a result of a single report.


class Attestation(Container):
    aggregation_bits: Bitlist[MAX_VALIDATORS_PER_COMMITTEE]
    data: AttestationData
    signature: BLSSignature

This is the form in which attestations make their way around the network. It is designed to be easily aggregatable: Attestations containing identical AttestationData can be combined into a single attestation by aggregating the signatures.

Attestations contain the same information as IndexedAttestations, but use knowledge of the validator committees at slots to compress the list of attesting validators down to a bitlist. Thus, Attestations are at least 5 times smaller than IndexedAttestations, and up to 35 times smaller (with 128 or 2048 validators per committee, respectively).

When a validator first broadcasts its attestation to the network, the aggregation_bits list will contain only a single bit set, and calling get_attesting_indices() on it will return a list containing only a single entry, the validator's own index.


class Deposit(Container):
    proof: Vector[Bytes32, DEPOSIT_CONTRACT_TREE_DEPTH + 1]  # Merkle path to deposit root
    data: DepositData

This container is used to include deposit data from prospective validators in beacon blocks so that they can be processed into beacon state.

The proof is a Merkle proof constructed by the block proposer that the DepositData corresponds to the previously agreed deposit root of the Eth1 contract's deposit tree. It is verified in process_deposit() by is_valid_merkle_branch().


class VoluntaryExit(Container):
    epoch: Epoch  # Earliest epoch when voluntary exit can be processed
    validator_index: ValidatorIndex

Voluntary exit messages are how a validator signals that it wants to cease being a validator. Blocks containg VoluntaryExit data for an epoch later than the current epoch are invalid, so nodes should buffer or ignore any future-dated exits they see.

VoluntaryExit objects are never used naked; they are always wrapped up into a SignedVoluntaryExit object.


class SyncAggregate(Container):
    sync_committee_bits: Bitvector[SYNC_COMMITTEE_SIZE]
    sync_committee_signature: BLSSignature

The prevailing sync committee is stored in the beacon state, so the SyncAggregates included in blocks need only use a bit vector to indicate which committee members signed off on the message.

The sync_committee_signature is the aggregate signature of all the validators referenced in the bit vector over the block root of the previous slot.

SyncAggregates are handled by process_sync_aggregate().

Created by Ben Edgington. Licensed under CC BY-SA 4.0. Published 2022-05-12 12:26 UTC. Commit 0cc9f0b.