github.com/prysmaticlabs/prysm@v1.4.4/tools/specs-checker/data/specs/phase0/beacon-chain.md (about)

     1  ```python
     2  def integer_squareroot(n: uint64) -> uint64:
     3      """
     4      Return the largest integer ``x`` such that ``x**2 <= n``.
     5      """
     6      x = n
     7      y = (x + 1) // 2
     8      while y < x:
     9          x = y
    10          y = (x + n // x) // 2
    11      return x
    12  ```
    13  ```python
    14  def xor(bytes_1: Bytes32, bytes_2: Bytes32) -> Bytes32:
    15      """
    16      Return the exclusive-or of two 32-byte strings.
    17      """
    18      return Bytes32(a ^ b for a, b in zip(bytes_1, bytes_2))
    19  ```
    20  ```python
    21  def bytes_to_uint64(data: bytes) -> uint64:
    22      """
    23      Return the integer deserialization of ``data`` interpreted as ``ENDIANNESS``-endian.
    24      """
    25      return uint64(int.from_bytes(data, ENDIANNESS))
    26  ```
    27  ```python
    28  def is_active_validator(validator: Validator, epoch: Epoch) -> bool:
    29      """
    30      Check if ``validator`` is active.
    31      """
    32      return validator.activation_epoch <= epoch < validator.exit_epoch
    33  ```
    34  ```python
    35  def is_eligible_for_activation_queue(validator: Validator) -> bool:
    36      """
    37      Check if ``validator`` is eligible to be placed into the activation queue.
    38      """
    39      return (
    40          validator.activation_eligibility_epoch == FAR_FUTURE_EPOCH
    41          and validator.effective_balance == MAX_EFFECTIVE_BALANCE
    42      )
    43  ```
    44  ```python
    45  def is_eligible_for_activation(state: BeaconState, validator: Validator) -> bool:
    46      """
    47      Check if ``validator`` is eligible for activation.
    48      """
    49      return (
    50          # Placement in queue is finalized
    51          validator.activation_eligibility_epoch <= state.finalized_checkpoint.epoch
    52          # Has not yet been activated
    53          and validator.activation_epoch == FAR_FUTURE_EPOCH
    54      )
    55  ```
    56  ```python
    57  def is_slashable_validator(validator: Validator, epoch: Epoch) -> bool:
    58      """
    59      Check if ``validator`` is slashable.
    60      """
    61      return (not validator.slashed) and (validator.activation_epoch <= epoch < validator.withdrawable_epoch)
    62  ```
    63  ```python
    64  def is_slashable_attestation_data(data_1: AttestationData, data_2: AttestationData) -> bool:
    65      """
    66      Check if ``data_1`` and ``data_2`` are slashable according to Casper FFG rules.
    67      """
    68      return (
    69          # Double vote
    70          (data_1 != data_2 and data_1.target.epoch == data_2.target.epoch) or
    71          # Surround vote
    72          (data_1.source.epoch < data_2.source.epoch and data_2.target.epoch < data_1.target.epoch)
    73      )
    74  ```
    75  ```python
    76  def is_valid_indexed_attestation(state: BeaconState, indexed_attestation: IndexedAttestation) -> bool:
    77      """
    78      Check if ``indexed_attestation`` is not empty, has sorted and unique indices and has a valid aggregate signature.
    79      """
    80      # Verify indices are sorted and unique
    81      indices = indexed_attestation.attesting_indices
    82      if len(indices) == 0 or not indices == sorted(set(indices)):
    83          return False
    84      # Verify aggregate signature
    85      pubkeys = [state.validators[i].pubkey for i in indices]
    86      domain = get_domain(state, DOMAIN_BEACON_ATTESTER, indexed_attestation.data.target.epoch)
    87      signing_root = compute_signing_root(indexed_attestation.data, domain)
    88      return bls.FastAggregateVerify(pubkeys, signing_root, indexed_attestation.signature)
    89  ```
    90  ```python
    91  def is_valid_merkle_branch(leaf: Bytes32, branch: Sequence[Bytes32], depth: uint64, index: uint64, root: Root) -> bool:
    92      """
    93      Check if ``leaf`` at ``index`` verifies against the Merkle ``root`` and ``branch``.
    94      """
    95      value = leaf
    96      for i in range(depth):
    97          if index // (2**i) % 2:
    98              value = hash(branch[i] + value)
    99          else:
   100              value = hash(value + branch[i])
   101      return value == root
   102  ```
   103  ```python
   104  def compute_shuffled_index(index: uint64, index_count: uint64, seed: Bytes32) -> uint64:
   105      """
   106      Return the shuffled index corresponding to ``seed`` (and ``index_count``).
   107      """
   108      assert index < index_count
   109  
   110      # Swap or not (https://link.springer.com/content/pdf/10.1007%2F978-3-642-32009-5_1.pdf)
   111      # See the 'generalized domain' algorithm on page 3
   112      for current_round in range(SHUFFLE_ROUND_COUNT):
   113          pivot = bytes_to_uint64(hash(seed + uint_to_bytes(uint8(current_round)))[0:8]) % index_count
   114          flip = (pivot + index_count - index) % index_count
   115          position = max(index, flip)
   116          source = hash(
   117              seed
   118              + uint_to_bytes(uint8(current_round))
   119              + uint_to_bytes(uint32(position // 256))
   120          )
   121          byte = uint8(source[(position % 256) // 8])
   122          bit = (byte >> (position % 8)) % 2
   123          index = flip if bit else index
   124  
   125      return index
   126  ```
   127  ```python
   128  def compute_proposer_index(state: BeaconState, indices: Sequence[ValidatorIndex], seed: Bytes32) -> ValidatorIndex:
   129      """
   130      Return from ``indices`` a random index sampled by effective balance.
   131      """
   132      assert len(indices) > 0
   133      MAX_RANDOM_BYTE = 2**8 - 1
   134      i = uint64(0)
   135      total = uint64(len(indices))
   136      while True:
   137          candidate_index = indices[compute_shuffled_index(i % total, total, seed)]
   138          random_byte = hash(seed + uint_to_bytes(uint64(i // 32)))[i % 32]
   139          effective_balance = state.validators[candidate_index].effective_balance
   140          if effective_balance * MAX_RANDOM_BYTE >= MAX_EFFECTIVE_BALANCE * random_byte:
   141              return candidate_index
   142          i += 1
   143  ```
   144  ```python
   145  def compute_committee(indices: Sequence[ValidatorIndex],
   146                        seed: Bytes32,
   147                        index: uint64,
   148                        count: uint64) -> Sequence[ValidatorIndex]:
   149      """
   150      Return the committee corresponding to ``indices``, ``seed``, ``index``, and committee ``count``.
   151      """
   152      start = (len(indices) * index) // count
   153      end = (len(indices) * uint64(index + 1)) // count
   154      return [indices[compute_shuffled_index(uint64(i), uint64(len(indices)), seed)] for i in range(start, end)]
   155  ```
   156  ```python
   157  def compute_epoch_at_slot(slot: Slot) -> Epoch:
   158      """
   159      Return the epoch number at ``slot``.
   160      """
   161      return Epoch(slot // SLOTS_PER_EPOCH)
   162  ```
   163  ```python
   164  def compute_start_slot_at_epoch(epoch: Epoch) -> Slot:
   165      """
   166      Return the start slot of ``epoch``.
   167      """
   168      return Slot(epoch * SLOTS_PER_EPOCH)
   169  ```
   170  ```python
   171  def compute_activation_exit_epoch(epoch: Epoch) -> Epoch:
   172      """
   173      Return the epoch during which validator activations and exits initiated in ``epoch`` take effect.
   174      """
   175      return Epoch(epoch + 1 + MAX_SEED_LOOKAHEAD)
   176  ```
   177  ```python
   178  def compute_fork_data_root(current_version: Version, genesis_validators_root: Root) -> Root:
   179      """
   180      Return the 32-byte fork data root for the ``current_version`` and ``genesis_validators_root``.
   181      This is used primarily in signature domains to avoid collisions across forks/chains.
   182      """
   183      return hash_tree_root(ForkData(
   184          current_version=current_version,
   185          genesis_validators_root=genesis_validators_root,
   186      ))
   187  ```
   188  ```python
   189  def compute_fork_digest(current_version: Version, genesis_validators_root: Root) -> ForkDigest:
   190      """
   191      Return the 4-byte fork digest for the ``current_version`` and ``genesis_validators_root``.
   192      This is a digest primarily used for domain separation on the p2p layer.
   193      4-bytes suffices for practical separation of forks/chains.
   194      """
   195      return ForkDigest(compute_fork_data_root(current_version, genesis_validators_root)[:4])
   196  ```
   197  ```python
   198  def compute_domain(domain_type: DomainType, fork_version: Version=None, genesis_validators_root: Root=None) -> Domain:
   199      """
   200      Return the domain for the ``domain_type`` and ``fork_version``.
   201      """
   202      if fork_version is None:
   203          fork_version = GENESIS_FORK_VERSION
   204      if genesis_validators_root is None:
   205          genesis_validators_root = Root()  # all bytes zero by default
   206      fork_data_root = compute_fork_data_root(fork_version, genesis_validators_root)
   207      return Domain(domain_type + fork_data_root[:28])
   208  ```
   209  ```python
   210  def compute_signing_root(ssz_object: SSZObject, domain: Domain) -> Root:
   211      """
   212      Return the signing root for the corresponding signing data.
   213      """
   214      return hash_tree_root(SigningData(
   215          object_root=hash_tree_root(ssz_object),
   216          domain=domain,
   217      ))
   218  ```
   219  ```python
   220  def get_current_epoch(state: BeaconState) -> Epoch:
   221      """
   222      Return the current epoch.
   223      """
   224      return compute_epoch_at_slot(state.slot)
   225  ```
   226  ```python
   227  def get_previous_epoch(state: BeaconState) -> Epoch:
   228      """`
   229      Return the previous epoch (unless the current epoch is ``GENESIS_EPOCH``).
   230      """
   231      current_epoch = get_current_epoch(state)
   232      return GENESIS_EPOCH if current_epoch == GENESIS_EPOCH else Epoch(current_epoch - 1)
   233  ```
   234  ```python
   235  def get_block_root(state: BeaconState, epoch: Epoch) -> Root:
   236      """
   237      Return the block root at the start of a recent ``epoch``.
   238      """
   239      return get_block_root_at_slot(state, compute_start_slot_at_epoch(epoch))
   240  ```
   241  ```python
   242  def get_block_root_at_slot(state: BeaconState, slot: Slot) -> Root:
   243      """
   244      Return the block root at a recent ``slot``.
   245      """
   246      assert slot < state.slot <= slot + SLOTS_PER_HISTORICAL_ROOT
   247      return state.block_roots[slot % SLOTS_PER_HISTORICAL_ROOT]
   248  ```
   249  ```python
   250  def get_randao_mix(state: BeaconState, epoch: Epoch) -> Bytes32:
   251      """
   252      Return the randao mix at a recent ``epoch``.
   253      """
   254      return state.randao_mixes[epoch % EPOCHS_PER_HISTORICAL_VECTOR]
   255  ```
   256  ```python
   257  def get_active_validator_indices(state: BeaconState, epoch: Epoch) -> Sequence[ValidatorIndex]:
   258      """
   259      Return the sequence of active validator indices at ``epoch``.
   260      """
   261      return [ValidatorIndex(i) for i, v in enumerate(state.validators) if is_active_validator(v, epoch)]
   262  ```
   263  ```python
   264  def get_validator_churn_limit(state: BeaconState) -> uint64:
   265      """
   266      Return the validator churn limit for the current epoch.
   267      """
   268      active_validator_indices = get_active_validator_indices(state, get_current_epoch(state))
   269      return max(MIN_PER_EPOCH_CHURN_LIMIT, uint64(len(active_validator_indices)) // CHURN_LIMIT_QUOTIENT)
   270  ```
   271  ```python
   272  def get_seed(state: BeaconState, epoch: Epoch, domain_type: DomainType) -> Bytes32:
   273      """
   274      Return the seed at ``epoch``.
   275      """
   276      mix = get_randao_mix(state, Epoch(epoch + EPOCHS_PER_HISTORICAL_VECTOR - MIN_SEED_LOOKAHEAD - 1))  # Avoid underflow
   277      return hash(domain_type + uint_to_bytes(epoch) + mix)
   278  ```
   279  ```python
   280  def get_committee_count_per_slot(state: BeaconState, epoch: Epoch) -> uint64:
   281      """
   282      Return the number of committees in each slot for the given ``epoch``.
   283      """
   284      return max(uint64(1), min(
   285          MAX_COMMITTEES_PER_SLOT,
   286          uint64(len(get_active_validator_indices(state, epoch))) // SLOTS_PER_EPOCH // TARGET_COMMITTEE_SIZE,
   287      ))
   288  ```
   289  ```python
   290  def get_beacon_committee(state: BeaconState, slot: Slot, index: CommitteeIndex) -> Sequence[ValidatorIndex]:
   291      """
   292      Return the beacon committee at ``slot`` for ``index``.
   293      """
   294      epoch = compute_epoch_at_slot(slot)
   295      committees_per_slot = get_committee_count_per_slot(state, epoch)
   296      return compute_committee(
   297          indices=get_active_validator_indices(state, epoch),
   298          seed=get_seed(state, epoch, DOMAIN_BEACON_ATTESTER),
   299          index=(slot % SLOTS_PER_EPOCH) * committees_per_slot + index,
   300          count=committees_per_slot * SLOTS_PER_EPOCH,
   301      )
   302  ```
   303  ```python
   304  def get_beacon_proposer_index(state: BeaconState) -> ValidatorIndex:
   305      """
   306      Return the beacon proposer index at the current slot.
   307      """
   308      epoch = get_current_epoch(state)
   309      seed = hash(get_seed(state, epoch, DOMAIN_BEACON_PROPOSER) + uint_to_bytes(state.slot))
   310      indices = get_active_validator_indices(state, epoch)
   311      return compute_proposer_index(state, indices, seed)
   312  ```
   313  ```python
   314  def get_total_balance(state: BeaconState, indices: Set[ValidatorIndex]) -> Gwei:
   315      """
   316      Return the combined effective balance of the ``indices``.
   317      ``EFFECTIVE_BALANCE_INCREMENT`` Gwei minimum to avoid divisions by zero.
   318      Math safe up to ~10B ETH, afterwhich this overflows uint64.
   319      """
   320      return Gwei(max(EFFECTIVE_BALANCE_INCREMENT, sum([state.validators[index].effective_balance for index in indices])))
   321  ```
   322  ```python
   323  def get_total_active_balance(state: BeaconState) -> Gwei:
   324      """
   325      Return the combined effective balance of the active validators.
   326      Note: ``get_total_balance`` returns ``EFFECTIVE_BALANCE_INCREMENT`` Gwei minimum to avoid divisions by zero.
   327      """
   328      return get_total_balance(state, set(get_active_validator_indices(state, get_current_epoch(state))))
   329  ```
   330  ```python
   331  def get_domain(state: BeaconState, domain_type: DomainType, epoch: Epoch=None) -> Domain:
   332      """
   333      Return the signature domain (fork version concatenated with domain type) of a message.
   334      """
   335      epoch = get_current_epoch(state) if epoch is None else epoch
   336      fork_version = state.fork.previous_version if epoch < state.fork.epoch else state.fork.current_version
   337      return compute_domain(domain_type, fork_version, state.genesis_validators_root)
   338  ```
   339  ```python
   340  def get_indexed_attestation(state: BeaconState, attestation: Attestation) -> IndexedAttestation:
   341      """
   342      Return the indexed attestation corresponding to ``attestation``.
   343      """
   344      attesting_indices = get_attesting_indices(state, attestation.data, attestation.aggregation_bits)
   345  
   346      return IndexedAttestation(
   347          attesting_indices=sorted(attesting_indices),
   348          data=attestation.data,
   349          signature=attestation.signature,
   350      )
   351  ```
   352  ```python
   353  def get_attesting_indices(state: BeaconState,
   354                            data: AttestationData,
   355                            bits: Bitlist[MAX_VALIDATORS_PER_COMMITTEE]) -> Set[ValidatorIndex]:
   356      """
   357      Return the set of attesting indices corresponding to ``data`` and ``bits``.
   358      """
   359      committee = get_beacon_committee(state, data.slot, data.index)
   360      return set(index for i, index in enumerate(committee) if bits[i])
   361  ```
   362  ```python
   363  def increase_balance(state: BeaconState, index: ValidatorIndex, delta: Gwei) -> None:
   364      """
   365      Increase the validator balance at index ``index`` by ``delta``.
   366      """
   367      state.balances[index] += delta
   368  ```
   369  ```python
   370  def decrease_balance(state: BeaconState, index: ValidatorIndex, delta: Gwei) -> None:
   371      """
   372      Decrease the validator balance at index ``index`` by ``delta``, with underflow protection.
   373      """
   374      state.balances[index] = 0 if delta > state.balances[index] else state.balances[index] - delta
   375  ```
   376  ```python
   377  def initiate_validator_exit(state: BeaconState, index: ValidatorIndex) -> None:
   378      """
   379      Initiate the exit of the validator with index ``index``.
   380      """
   381      # Return if validator already initiated exit
   382      validator = state.validators[index]
   383      if validator.exit_epoch != FAR_FUTURE_EPOCH:
   384          return
   385  
   386      # Compute exit queue epoch
   387      exit_epochs = [v.exit_epoch for v in state.validators if v.exit_epoch != FAR_FUTURE_EPOCH]
   388      exit_queue_epoch = max(exit_epochs + [compute_activation_exit_epoch(get_current_epoch(state))])
   389      exit_queue_churn = len([v for v in state.validators if v.exit_epoch == exit_queue_epoch])
   390      if exit_queue_churn >= get_validator_churn_limit(state):
   391          exit_queue_epoch += Epoch(1)
   392  
   393      # Set validator exit epoch and withdrawable epoch
   394      validator.exit_epoch = exit_queue_epoch
   395      validator.withdrawable_epoch = Epoch(validator.exit_epoch + MIN_VALIDATOR_WITHDRAWABILITY_DELAY)
   396  ```
   397  ```python
   398  def slash_validator(state: BeaconState,
   399                      slashed_index: ValidatorIndex,
   400                      whistleblower_index: ValidatorIndex=None) -> None:
   401      """
   402      Slash the validator with index ``slashed_index``.
   403      """
   404      epoch = get_current_epoch(state)
   405      initiate_validator_exit(state, slashed_index)
   406      validator = state.validators[slashed_index]
   407      validator.slashed = True
   408      validator.withdrawable_epoch = max(validator.withdrawable_epoch, Epoch(epoch + EPOCHS_PER_SLASHINGS_VECTOR))
   409      state.slashings[epoch % EPOCHS_PER_SLASHINGS_VECTOR] += validator.effective_balance
   410      decrease_balance(state, slashed_index, validator.effective_balance // MIN_SLASHING_PENALTY_QUOTIENT)
   411  
   412      # Apply proposer and whistleblower rewards
   413      proposer_index = get_beacon_proposer_index(state)
   414      if whistleblower_index is None:
   415          whistleblower_index = proposer_index
   416      whistleblower_reward = Gwei(validator.effective_balance // WHISTLEBLOWER_REWARD_QUOTIENT)
   417      proposer_reward = Gwei(whistleblower_reward // PROPOSER_REWARD_QUOTIENT)
   418      increase_balance(state, proposer_index, proposer_reward)
   419      increase_balance(state, whistleblower_index, Gwei(whistleblower_reward - proposer_reward))
   420  ```
   421  ```python
   422  def initialize_beacon_state_from_eth1(eth1_block_hash: Bytes32,
   423                                        eth1_timestamp: uint64,
   424                                        deposits: Sequence[Deposit]) -> BeaconState:
   425      fork = Fork(
   426          previous_version=GENESIS_FORK_VERSION,
   427          current_version=GENESIS_FORK_VERSION,
   428          epoch=GENESIS_EPOCH,
   429      )
   430      state = BeaconState(
   431          genesis_time=eth1_timestamp + GENESIS_DELAY,
   432          fork=fork,
   433          eth1_data=Eth1Data(block_hash=eth1_block_hash, deposit_count=uint64(len(deposits))),
   434          latest_block_header=BeaconBlockHeader(body_root=hash_tree_root(BeaconBlockBody())),
   435          randao_mixes=[eth1_block_hash] * EPOCHS_PER_HISTORICAL_VECTOR,  # Seed RANDAO with Eth1 entropy
   436      )
   437  
   438      # Process deposits
   439      leaves = list(map(lambda deposit: deposit.data, deposits))
   440      for index, deposit in enumerate(deposits):
   441          deposit_data_list = List[DepositData, 2**DEPOSIT_CONTRACT_TREE_DEPTH](*leaves[:index + 1])
   442          state.eth1_data.deposit_root = hash_tree_root(deposit_data_list)
   443          process_deposit(state, deposit)
   444  
   445      # Process activations
   446      for index, validator in enumerate(state.validators):
   447          balance = state.balances[index]
   448          validator.effective_balance = min(balance - balance % EFFECTIVE_BALANCE_INCREMENT, MAX_EFFECTIVE_BALANCE)
   449          if validator.effective_balance == MAX_EFFECTIVE_BALANCE:
   450              validator.activation_eligibility_epoch = GENESIS_EPOCH
   451              validator.activation_epoch = GENESIS_EPOCH
   452  
   453      # Set genesis validators root for domain separation and chain versioning
   454      state.genesis_validators_root = hash_tree_root(state.validators)
   455  
   456      return state
   457  ```
   458  ```python
   459  def is_valid_genesis_state(state: BeaconState) -> bool:
   460      if state.genesis_time < MIN_GENESIS_TIME:
   461          return False
   462      if len(get_active_validator_indices(state, GENESIS_EPOCH)) < MIN_GENESIS_ACTIVE_VALIDATOR_COUNT:
   463          return False
   464      return True
   465  ```
   466  ```python
   467  def state_transition(state: BeaconState, signed_block: SignedBeaconBlock, validate_result: bool=True) -> None:
   468      block = signed_block.message
   469      # Process slots (including those with no blocks) since block
   470      process_slots(state, block.slot)
   471      # Verify signature
   472      if validate_result:
   473          assert verify_block_signature(state, signed_block)
   474      # Process block
   475      process_block(state, block)
   476      # Verify state root
   477      if validate_result:
   478          assert block.state_root == hash_tree_root(state)
   479  ```
   480  ```python
   481  def verify_block_signature(state: BeaconState, signed_block: SignedBeaconBlock) -> bool:
   482      proposer = state.validators[signed_block.message.proposer_index]
   483      signing_root = compute_signing_root(signed_block.message, get_domain(state, DOMAIN_BEACON_PROPOSER))
   484      return bls.Verify(proposer.pubkey, signing_root, signed_block.signature)
   485  ```
   486  ```python
   487  def process_slots(state: BeaconState, slot: Slot) -> None:
   488      assert state.slot < slot
   489      while state.slot < slot:
   490          process_slot(state)
   491          # Process epoch on the start slot of the next epoch
   492          if (state.slot + 1) % SLOTS_PER_EPOCH == 0:
   493              process_epoch(state)
   494          state.slot = Slot(state.slot + 1)
   495  ```
   496  ```python
   497  def process_slot(state: BeaconState) -> None:
   498      # Cache state root
   499      previous_state_root = hash_tree_root(state)
   500      state.state_roots[state.slot % SLOTS_PER_HISTORICAL_ROOT] = previous_state_root
   501      # Cache latest block header state root
   502      if state.latest_block_header.state_root == Bytes32():
   503          state.latest_block_header.state_root = previous_state_root
   504      # Cache block root
   505      previous_block_root = hash_tree_root(state.latest_block_header)
   506      state.block_roots[state.slot % SLOTS_PER_HISTORICAL_ROOT] = previous_block_root
   507  ```
   508  ```python
   509  def process_epoch(state: BeaconState) -> None:
   510      process_justification_and_finalization(state)
   511      process_rewards_and_penalties(state)
   512      process_registry_updates(state)
   513      process_slashings(state)
   514      process_eth1_data_reset(state)
   515      process_effective_balance_updates(state)
   516      process_slashings_reset(state)
   517      process_randao_mixes_reset(state)
   518      process_historical_roots_update(state)
   519      process_participation_record_updates(state)
   520  ```
   521  ```python
   522  def get_matching_source_attestations(state: BeaconState, epoch: Epoch) -> Sequence[PendingAttestation]:
   523      assert epoch in (get_previous_epoch(state), get_current_epoch(state))
   524      return state.current_epoch_attestations if epoch == get_current_epoch(state) else state.previous_epoch_attestations
   525  ```
   526  ```python
   527  def get_matching_target_attestations(state: BeaconState, epoch: Epoch) -> Sequence[PendingAttestation]:
   528      return [
   529          a for a in get_matching_source_attestations(state, epoch)
   530          if a.data.target.root == get_block_root(state, epoch)
   531      ]
   532  ```
   533  ```python
   534  def get_matching_head_attestations(state: BeaconState, epoch: Epoch) -> Sequence[PendingAttestation]:
   535      return [
   536          a for a in get_matching_target_attestations(state, epoch)
   537          if a.data.beacon_block_root == get_block_root_at_slot(state, a.data.slot)
   538      ]
   539  ```
   540  ```python
   541  def get_unslashed_attesting_indices(state: BeaconState,
   542                                      attestations: Sequence[PendingAttestation]) -> Set[ValidatorIndex]:
   543      output = set()  # type: Set[ValidatorIndex]
   544      for a in attestations:
   545          output = output.union(get_attesting_indices(state, a.data, a.aggregation_bits))
   546      return set(filter(lambda index: not state.validators[index].slashed, output))
   547  ```
   548  ```python
   549  def get_attesting_balance(state: BeaconState, attestations: Sequence[PendingAttestation]) -> Gwei:
   550      """
   551      Return the combined effective balance of the set of unslashed validators participating in ``attestations``.
   552      Note: ``get_total_balance`` returns ``EFFECTIVE_BALANCE_INCREMENT`` Gwei minimum to avoid divisions by zero.
   553      """
   554      return get_total_balance(state, get_unslashed_attesting_indices(state, attestations))
   555  ```
   556  ```python
   557  def process_justification_and_finalization(state: BeaconState) -> None:
   558      # Initial FFG checkpoint values have a `0x00` stub for `root`.
   559      # Skip FFG updates in the first two epochs to avoid corner cases that might result in modifying this stub.
   560      if get_current_epoch(state) <= GENESIS_EPOCH + 1:
   561          return
   562      previous_attestations = get_matching_target_attestations(state, get_previous_epoch(state))
   563      current_attestations = get_matching_target_attestations(state, get_current_epoch(state))
   564      total_active_balance = get_total_active_balance(state)
   565      previous_target_balance = get_attesting_balance(state, previous_attestations)
   566      current_target_balance = get_attesting_balance(state, current_attestations)
   567      weigh_justification_and_finalization(state, total_active_balance, previous_target_balance, current_target_balance)
   568  ```
   569  ```python
   570  def weigh_justification_and_finalization(state: BeaconState,
   571                                           total_active_balance: Gwei,
   572                                           previous_epoch_target_balance: Gwei,
   573                                           current_epoch_target_balance: Gwei) -> None:
   574      previous_epoch = get_previous_epoch(state)
   575      current_epoch = get_current_epoch(state)
   576      old_previous_justified_checkpoint = state.previous_justified_checkpoint
   577      old_current_justified_checkpoint = state.current_justified_checkpoint
   578  
   579      # Process justifications
   580      state.previous_justified_checkpoint = state.current_justified_checkpoint
   581      state.justification_bits[1:] = state.justification_bits[:JUSTIFICATION_BITS_LENGTH - 1]
   582      state.justification_bits[0] = 0b0
   583      if previous_epoch_target_balance * 3 >= total_active_balance * 2:
   584          state.current_justified_checkpoint = Checkpoint(epoch=previous_epoch,
   585                                                          root=get_block_root(state, previous_epoch))
   586          state.justification_bits[1] = 0b1
   587      if current_epoch_target_balance * 3 >= total_active_balance * 2:
   588          state.current_justified_checkpoint = Checkpoint(epoch=current_epoch,
   589                                                          root=get_block_root(state, current_epoch))
   590          state.justification_bits[0] = 0b1
   591  
   592      # Process finalizations
   593      bits = state.justification_bits
   594      # The 2nd/3rd/4th most recent epochs are justified, the 2nd using the 4th as source
   595      if all(bits[1:4]) and old_previous_justified_checkpoint.epoch + 3 == current_epoch:
   596          state.finalized_checkpoint = old_previous_justified_checkpoint
   597      # The 2nd/3rd most recent epochs are justified, the 2nd using the 3rd as source
   598      if all(bits[1:3]) and old_previous_justified_checkpoint.epoch + 2 == current_epoch:
   599          state.finalized_checkpoint = old_previous_justified_checkpoint
   600      # The 1st/2nd/3rd most recent epochs are justified, the 1st using the 3rd as source
   601      if all(bits[0:3]) and old_current_justified_checkpoint.epoch + 2 == current_epoch:
   602          state.finalized_checkpoint = old_current_justified_checkpoint
   603      # The 1st/2nd most recent epochs are justified, the 1st using the 2nd as source
   604      if all(bits[0:2]) and old_current_justified_checkpoint.epoch + 1 == current_epoch:
   605          state.finalized_checkpoint = old_current_justified_checkpoint
   606  ```
   607  ```python
   608  def get_base_reward(state: BeaconState, index: ValidatorIndex) -> Gwei:
   609      total_balance = get_total_active_balance(state)
   610      effective_balance = state.validators[index].effective_balance
   611      return Gwei(effective_balance * BASE_REWARD_FACTOR // integer_squareroot(total_balance) // BASE_REWARDS_PER_EPOCH)
   612  ```
   613  ```python
   614  def get_proposer_reward(state: BeaconState, attesting_index: ValidatorIndex) -> Gwei:
   615      return Gwei(get_base_reward(state, attesting_index) // PROPOSER_REWARD_QUOTIENT)
   616  ```
   617  ```python
   618  def get_finality_delay(state: BeaconState) -> uint64:
   619      return get_previous_epoch(state) - state.finalized_checkpoint.epoch
   620  ```
   621  ```python
   622  def is_in_inactivity_leak(state: BeaconState) -> bool:
   623      return get_finality_delay(state) > MIN_EPOCHS_TO_INACTIVITY_PENALTY
   624  ```
   625  ```python
   626  def get_eligible_validator_indices(state: BeaconState) -> Sequence[ValidatorIndex]:
   627      previous_epoch = get_previous_epoch(state)
   628      return [
   629          ValidatorIndex(index) for index, v in enumerate(state.validators)
   630          if is_active_validator(v, previous_epoch) or (v.slashed and previous_epoch + 1 < v.withdrawable_epoch)
   631      ]
   632  ```
   633  ```python
   634  def get_attestation_component_deltas(state: BeaconState,
   635                                       attestations: Sequence[PendingAttestation]
   636                                       ) -> Tuple[Sequence[Gwei], Sequence[Gwei]]:
   637      """
   638      Helper with shared logic for use by get source, target, and head deltas functions
   639      """
   640      rewards = [Gwei(0)] * len(state.validators)
   641      penalties = [Gwei(0)] * len(state.validators)
   642      total_balance = get_total_active_balance(state)
   643      unslashed_attesting_indices = get_unslashed_attesting_indices(state, attestations)
   644      attesting_balance = get_total_balance(state, unslashed_attesting_indices)
   645      for index in get_eligible_validator_indices(state):
   646          if index in unslashed_attesting_indices:
   647              increment = EFFECTIVE_BALANCE_INCREMENT  # Factored out from balance totals to avoid uint64 overflow
   648              if is_in_inactivity_leak(state):
   649                  # Since full base reward will be canceled out by inactivity penalty deltas,
   650                  # optimal participation receives full base reward compensation here.
   651                  rewards[index] += get_base_reward(state, index)
   652              else:
   653                  reward_numerator = get_base_reward(state, index) * (attesting_balance // increment)
   654                  rewards[index] += reward_numerator // (total_balance // increment)
   655          else:
   656              penalties[index] += get_base_reward(state, index)
   657      return rewards, penalties
   658  ```
   659  ```python
   660  def get_source_deltas(state: BeaconState) -> Tuple[Sequence[Gwei], Sequence[Gwei]]:
   661      """
   662      Return attester micro-rewards/penalties for source-vote for each validator.
   663      """
   664      matching_source_attestations = get_matching_source_attestations(state, get_previous_epoch(state))
   665      return get_attestation_component_deltas(state, matching_source_attestations)
   666  ```
   667  ```python
   668  def get_target_deltas(state: BeaconState) -> Tuple[Sequence[Gwei], Sequence[Gwei]]:
   669      """
   670      Return attester micro-rewards/penalties for target-vote for each validator.
   671      """
   672      matching_target_attestations = get_matching_target_attestations(state, get_previous_epoch(state))
   673      return get_attestation_component_deltas(state, matching_target_attestations)
   674  ```
   675  ```python
   676  def get_head_deltas(state: BeaconState) -> Tuple[Sequence[Gwei], Sequence[Gwei]]:
   677      """
   678      Return attester micro-rewards/penalties for head-vote for each validator.
   679      """
   680      matching_head_attestations = get_matching_head_attestations(state, get_previous_epoch(state))
   681      return get_attestation_component_deltas(state, matching_head_attestations)
   682  ```
   683  ```python
   684  def get_inclusion_delay_deltas(state: BeaconState) -> Tuple[Sequence[Gwei], Sequence[Gwei]]:
   685      """
   686      Return proposer and inclusion delay micro-rewards/penalties for each validator.
   687      """
   688      rewards = [Gwei(0) for _ in range(len(state.validators))]
   689      matching_source_attestations = get_matching_source_attestations(state, get_previous_epoch(state))
   690      for index in get_unslashed_attesting_indices(state, matching_source_attestations):
   691          attestation = min([
   692              a for a in matching_source_attestations
   693              if index in get_attesting_indices(state, a.data, a.aggregation_bits)
   694          ], key=lambda a: a.inclusion_delay)
   695          rewards[attestation.proposer_index] += get_proposer_reward(state, index)
   696          max_attester_reward = Gwei(get_base_reward(state, index) - get_proposer_reward(state, index))
   697          rewards[index] += Gwei(max_attester_reward // attestation.inclusion_delay)
   698  
   699      # No penalties associated with inclusion delay
   700      penalties = [Gwei(0) for _ in range(len(state.validators))]
   701      return rewards, penalties
   702  ```
   703  ```python
   704  def get_inactivity_penalty_deltas(state: BeaconState) -> Tuple[Sequence[Gwei], Sequence[Gwei]]:
   705      """
   706      Return inactivity reward/penalty deltas for each validator.
   707      """
   708      penalties = [Gwei(0) for _ in range(len(state.validators))]
   709      if is_in_inactivity_leak(state):
   710          matching_target_attestations = get_matching_target_attestations(state, get_previous_epoch(state))
   711          matching_target_attesting_indices = get_unslashed_attesting_indices(state, matching_target_attestations)
   712          for index in get_eligible_validator_indices(state):
   713              # If validator is performing optimally this cancels all rewards for a neutral balance
   714              base_reward = get_base_reward(state, index)
   715              penalties[index] += Gwei(BASE_REWARDS_PER_EPOCH * base_reward - get_proposer_reward(state, index))
   716              if index not in matching_target_attesting_indices:
   717                  effective_balance = state.validators[index].effective_balance
   718                  penalties[index] += Gwei(effective_balance * get_finality_delay(state) // INACTIVITY_PENALTY_QUOTIENT)
   719  
   720      # No rewards associated with inactivity penalties
   721      rewards = [Gwei(0) for _ in range(len(state.validators))]
   722      return rewards, penalties
   723  ```
   724  ```python
   725  def get_attestation_deltas(state: BeaconState) -> Tuple[Sequence[Gwei], Sequence[Gwei]]:
   726      """
   727      Return attestation reward/penalty deltas for each validator.
   728      """
   729      source_rewards, source_penalties = get_source_deltas(state)
   730      target_rewards, target_penalties = get_target_deltas(state)
   731      head_rewards, head_penalties = get_head_deltas(state)
   732      inclusion_delay_rewards, _ = get_inclusion_delay_deltas(state)
   733      _, inactivity_penalties = get_inactivity_penalty_deltas(state)
   734  
   735      rewards = [
   736          source_rewards[i] + target_rewards[i] + head_rewards[i] + inclusion_delay_rewards[i]
   737          for i in range(len(state.validators))
   738      ]
   739  
   740      penalties = [
   741          source_penalties[i] + target_penalties[i] + head_penalties[i] + inactivity_penalties[i]
   742          for i in range(len(state.validators))
   743      ]
   744  
   745      return rewards, penalties
   746  ```
   747  ```python
   748  def process_rewards_and_penalties(state: BeaconState) -> None:
   749      # No rewards are applied at the end of `GENESIS_EPOCH` because rewards are for work done in the previous epoch
   750      if get_current_epoch(state) == GENESIS_EPOCH:
   751          return
   752  
   753      rewards, penalties = get_attestation_deltas(state)
   754      for index in range(len(state.validators)):
   755          increase_balance(state, ValidatorIndex(index), rewards[index])
   756          decrease_balance(state, ValidatorIndex(index), penalties[index])
   757  ```
   758  ```python
   759  def process_registry_updates(state: BeaconState) -> None:
   760      # Process activation eligibility and ejections
   761      for index, validator in enumerate(state.validators):
   762          if is_eligible_for_activation_queue(validator):
   763              validator.activation_eligibility_epoch = get_current_epoch(state) + 1
   764  
   765          if is_active_validator(validator, get_current_epoch(state)) and validator.effective_balance <= EJECTION_BALANCE:
   766              initiate_validator_exit(state, ValidatorIndex(index))
   767  
   768      # Queue validators eligible for activation and not yet dequeued for activation
   769      activation_queue = sorted([
   770          index for index, validator in enumerate(state.validators)
   771          if is_eligible_for_activation(state, validator)
   772          # Order by the sequence of activation_eligibility_epoch setting and then index
   773      ], key=lambda index: (state.validators[index].activation_eligibility_epoch, index))
   774      # Dequeued validators for activation up to churn limit
   775      for index in activation_queue[:get_validator_churn_limit(state)]:
   776          validator = state.validators[index]
   777          validator.activation_epoch = compute_activation_exit_epoch(get_current_epoch(state))
   778  ```
   779  ```python
   780  def process_slashings(state: BeaconState) -> None:
   781      epoch = get_current_epoch(state)
   782      total_balance = get_total_active_balance(state)
   783      adjusted_total_slashing_balance = min(sum(state.slashings) * PROPORTIONAL_SLASHING_MULTIPLIER, total_balance)
   784      for index, validator in enumerate(state.validators):
   785          if validator.slashed and epoch + EPOCHS_PER_SLASHINGS_VECTOR // 2 == validator.withdrawable_epoch:
   786              increment = EFFECTIVE_BALANCE_INCREMENT  # Factored out from penalty numerator to avoid uint64 overflow
   787              penalty_numerator = validator.effective_balance // increment * adjusted_total_slashing_balance
   788              penalty = penalty_numerator // total_balance * increment
   789              decrease_balance(state, ValidatorIndex(index), penalty)
   790  ```
   791  ```python
   792  def process_eth1_data_reset(state: BeaconState) -> None:
   793      next_epoch = Epoch(get_current_epoch(state) + 1)
   794      # Reset eth1 data votes
   795      if next_epoch % EPOCHS_PER_ETH1_VOTING_PERIOD == 0:
   796          state.eth1_data_votes = []
   797  ```
   798  ```python
   799  def process_effective_balance_updates(state: BeaconState) -> None:
   800      # Update effective balances with hysteresis
   801      for index, validator in enumerate(state.validators):
   802          balance = state.balances[index]
   803          HYSTERESIS_INCREMENT = uint64(EFFECTIVE_BALANCE_INCREMENT // HYSTERESIS_QUOTIENT)
   804          DOWNWARD_THRESHOLD = HYSTERESIS_INCREMENT * HYSTERESIS_DOWNWARD_MULTIPLIER
   805          UPWARD_THRESHOLD = HYSTERESIS_INCREMENT * HYSTERESIS_UPWARD_MULTIPLIER
   806          if (
   807              balance + DOWNWARD_THRESHOLD < validator.effective_balance
   808              or validator.effective_balance + UPWARD_THRESHOLD < balance
   809          ):
   810              validator.effective_balance = min(balance - balance % EFFECTIVE_BALANCE_INCREMENT, MAX_EFFECTIVE_BALANCE)
   811  ```
   812  ```python
   813  def process_slashings_reset(state: BeaconState) -> None:
   814      next_epoch = Epoch(get_current_epoch(state) + 1)
   815      # Reset slashings
   816      state.slashings[next_epoch % EPOCHS_PER_SLASHINGS_VECTOR] = Gwei(0)
   817  ```
   818  ```python
   819  def process_randao_mixes_reset(state: BeaconState) -> None:
   820      current_epoch = get_current_epoch(state)
   821      next_epoch = Epoch(current_epoch + 1)
   822      # Set randao mix
   823      state.randao_mixes[next_epoch % EPOCHS_PER_HISTORICAL_VECTOR] = get_randao_mix(state, current_epoch)
   824  ```
   825  ```python
   826  def process_historical_roots_update(state: BeaconState) -> None:
   827      # Set historical root accumulator
   828      next_epoch = Epoch(get_current_epoch(state) + 1)
   829      if next_epoch % (SLOTS_PER_HISTORICAL_ROOT // SLOTS_PER_EPOCH) == 0:
   830          historical_batch = HistoricalBatch(block_roots=state.block_roots, state_roots=state.state_roots)
   831          state.historical_roots.append(hash_tree_root(historical_batch))
   832  ```
   833  ```python
   834  def process_participation_record_updates(state: BeaconState) -> None:
   835      # Rotate current/previous epoch attestations
   836      state.previous_epoch_attestations = state.current_epoch_attestations
   837      state.current_epoch_attestations = []
   838  ```
   839  ```python
   840  def process_block(state: BeaconState, block: BeaconBlock) -> None:
   841      process_block_header(state, block)
   842      process_randao(state, block.body)
   843      process_eth1_data(state, block.body)
   844      process_operations(state, block.body)
   845  ```
   846  ```python
   847  def process_block_header(state: BeaconState, block: BeaconBlock) -> None:
   848      # Verify that the slots match
   849      assert block.slot == state.slot
   850      # Verify that the block is newer than latest block header
   851      assert block.slot > state.latest_block_header.slot
   852      # Verify that proposer index is the correct index
   853      assert block.proposer_index == get_beacon_proposer_index(state)
   854      # Verify that the parent matches
   855      assert block.parent_root == hash_tree_root(state.latest_block_header)
   856      # Cache current block as the new latest block
   857      state.latest_block_header = BeaconBlockHeader(
   858          slot=block.slot,
   859          proposer_index=block.proposer_index,
   860          parent_root=block.parent_root,
   861          state_root=Bytes32(),  # Overwritten in the next process_slot call
   862          body_root=hash_tree_root(block.body),
   863      )
   864  
   865      # Verify proposer is not slashed
   866      proposer = state.validators[block.proposer_index]
   867      assert not proposer.slashed
   868  ```
   869  ```python
   870  def process_randao(state: BeaconState, body: BeaconBlockBody) -> None:
   871      epoch = get_current_epoch(state)
   872      # Verify RANDAO reveal
   873      proposer = state.validators[get_beacon_proposer_index(state)]
   874      signing_root = compute_signing_root(epoch, get_domain(state, DOMAIN_RANDAO))
   875      assert bls.Verify(proposer.pubkey, signing_root, body.randao_reveal)
   876      # Mix in RANDAO reveal
   877      mix = xor(get_randao_mix(state, epoch), hash(body.randao_reveal))
   878      state.randao_mixes[epoch % EPOCHS_PER_HISTORICAL_VECTOR] = mix
   879  ```
   880  ```python
   881  def process_eth1_data(state: BeaconState, body: BeaconBlockBody) -> None:
   882      state.eth1_data_votes.append(body.eth1_data)
   883      if state.eth1_data_votes.count(body.eth1_data) * 2 > EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH:
   884          state.eth1_data = body.eth1_data
   885  ```
   886  ```python
   887  def process_operations(state: BeaconState, body: BeaconBlockBody) -> None:
   888      # Verify that outstanding deposits are processed up to the maximum number of deposits
   889      assert len(body.deposits) == min(MAX_DEPOSITS, state.eth1_data.deposit_count - state.eth1_deposit_index)
   890  
   891      def for_ops(operations: Sequence[Any], fn: Callable[[BeaconState, Any], None]) -> None:
   892          for operation in operations:
   893              fn(state, operation)
   894  
   895      for_ops(body.proposer_slashings, process_proposer_slashing)
   896      for_ops(body.attester_slashings, process_attester_slashing)
   897      for_ops(body.attestations, process_attestation)
   898      for_ops(body.deposits, process_deposit)
   899      for_ops(body.voluntary_exits, process_voluntary_exit)
   900  ```
   901  ```python
   902  def process_proposer_slashing(state: BeaconState, proposer_slashing: ProposerSlashing) -> None:
   903      header_1 = proposer_slashing.signed_header_1.message
   904      header_2 = proposer_slashing.signed_header_2.message
   905  
   906      # Verify header slots match
   907      assert header_1.slot == header_2.slot
   908      # Verify header proposer indices match
   909      assert header_1.proposer_index == header_2.proposer_index
   910      # Verify the headers are different
   911      assert header_1 != header_2
   912      # Verify the proposer is slashable
   913      proposer = state.validators[header_1.proposer_index]
   914      assert is_slashable_validator(proposer, get_current_epoch(state))
   915      # Verify signatures
   916      for signed_header in (proposer_slashing.signed_header_1, proposer_slashing.signed_header_2):
   917          domain = get_domain(state, DOMAIN_BEACON_PROPOSER, compute_epoch_at_slot(signed_header.message.slot))
   918          signing_root = compute_signing_root(signed_header.message, domain)
   919          assert bls.Verify(proposer.pubkey, signing_root, signed_header.signature)
   920  
   921      slash_validator(state, header_1.proposer_index)
   922  ```
   923  ```python
   924  def process_attester_slashing(state: BeaconState, attester_slashing: AttesterSlashing) -> None:
   925      attestation_1 = attester_slashing.attestation_1
   926      attestation_2 = attester_slashing.attestation_2
   927      assert is_slashable_attestation_data(attestation_1.data, attestation_2.data)
   928      assert is_valid_indexed_attestation(state, attestation_1)
   929      assert is_valid_indexed_attestation(state, attestation_2)
   930  
   931      slashed_any = False
   932      indices = set(attestation_1.attesting_indices).intersection(attestation_2.attesting_indices)
   933      for index in sorted(indices):
   934          if is_slashable_validator(state.validators[index], get_current_epoch(state)):
   935              slash_validator(state, index)
   936              slashed_any = True
   937      assert slashed_any
   938  ```
   939  ```python
   940  def process_attestation(state: BeaconState, attestation: Attestation) -> None:
   941      data = attestation.data
   942      assert data.target.epoch in (get_previous_epoch(state), get_current_epoch(state))
   943      assert data.target.epoch == compute_epoch_at_slot(data.slot)
   944      assert data.slot + MIN_ATTESTATION_INCLUSION_DELAY <= state.slot <= data.slot + SLOTS_PER_EPOCH
   945      assert data.index < get_committee_count_per_slot(state, data.target.epoch)
   946  
   947      committee = get_beacon_committee(state, data.slot, data.index)
   948      assert len(attestation.aggregation_bits) == len(committee)
   949  
   950      pending_attestation = PendingAttestation(
   951          data=data,
   952          aggregation_bits=attestation.aggregation_bits,
   953          inclusion_delay=state.slot - data.slot,
   954          proposer_index=get_beacon_proposer_index(state),
   955      )
   956  
   957      if data.target.epoch == get_current_epoch(state):
   958          assert data.source == state.current_justified_checkpoint
   959          state.current_epoch_attestations.append(pending_attestation)
   960      else:
   961          assert data.source == state.previous_justified_checkpoint
   962          state.previous_epoch_attestations.append(pending_attestation)
   963  
   964      # Verify signature
   965      assert is_valid_indexed_attestation(state, get_indexed_attestation(state, attestation))
   966  ```
   967  ```python
   968  def get_validator_from_deposit(state: BeaconState, deposit: Deposit) -> Validator:
   969      amount = deposit.data.amount
   970      effective_balance = min(amount - amount % EFFECTIVE_BALANCE_INCREMENT, MAX_EFFECTIVE_BALANCE)
   971  
   972      return Validator(
   973          pubkey=deposit.data.pubkey,
   974          withdrawal_credentials=deposit.data.withdrawal_credentials,
   975          activation_eligibility_epoch=FAR_FUTURE_EPOCH,
   976          activation_epoch=FAR_FUTURE_EPOCH,
   977          exit_epoch=FAR_FUTURE_EPOCH,
   978          withdrawable_epoch=FAR_FUTURE_EPOCH,
   979          effective_balance=effective_balance,
   980      )
   981  ```
   982  ```python
   983  def process_deposit(state: BeaconState, deposit: Deposit) -> None:
   984      # Verify the Merkle branch
   985      assert is_valid_merkle_branch(
   986          leaf=hash_tree_root(deposit.data),
   987          branch=deposit.proof,
   988          depth=DEPOSIT_CONTRACT_TREE_DEPTH + 1,  # Add 1 for the List length mix-in
   989          index=state.eth1_deposit_index,
   990          root=state.eth1_data.deposit_root,
   991      )
   992  
   993      # Deposits must be processed in order
   994      state.eth1_deposit_index += 1
   995  
   996      pubkey = deposit.data.pubkey
   997      amount = deposit.data.amount
   998      validator_pubkeys = [v.pubkey for v in state.validators]
   999      if pubkey not in validator_pubkeys:
  1000          # Verify the deposit signature (proof of possession) which is not checked by the deposit contract
  1001          deposit_message = DepositMessage(
  1002              pubkey=deposit.data.pubkey,
  1003              withdrawal_credentials=deposit.data.withdrawal_credentials,
  1004              amount=deposit.data.amount,
  1005          )
  1006          domain = compute_domain(DOMAIN_DEPOSIT)  # Fork-agnostic domain since deposits are valid across forks
  1007          signing_root = compute_signing_root(deposit_message, domain)
  1008          if not bls.Verify(pubkey, signing_root, deposit.data.signature):
  1009              return
  1010  
  1011          # Add validator and balance entries
  1012          state.validators.append(get_validator_from_deposit(state, deposit))
  1013          state.balances.append(amount)
  1014      else:
  1015          # Increase balance by deposit amount
  1016          index = ValidatorIndex(validator_pubkeys.index(pubkey))
  1017          increase_balance(state, index, amount)
  1018  ```
  1019  ```python
  1020  def process_voluntary_exit(state: BeaconState, signed_voluntary_exit: SignedVoluntaryExit) -> None:
  1021      voluntary_exit = signed_voluntary_exit.message
  1022      validator = state.validators[voluntary_exit.validator_index]
  1023      # Verify the validator is active
  1024      assert is_active_validator(validator, get_current_epoch(state))
  1025      # Verify exit has not been initiated
  1026      assert validator.exit_epoch == FAR_FUTURE_EPOCH
  1027      # Exits must specify an epoch when they become valid; they are not valid before then
  1028      assert get_current_epoch(state) >= voluntary_exit.epoch
  1029      # Verify the validator has been active long enough
  1030      assert get_current_epoch(state) >= validator.activation_epoch + SHARD_COMMITTEE_PERIOD
  1031      # Verify signature
  1032      domain = get_domain(state, DOMAIN_VOLUNTARY_EXIT, voluntary_exit.epoch)
  1033      signing_root = compute_signing_root(voluntary_exit, domain)
  1034      assert bls.Verify(validator.pubkey, signing_root, signed_voluntary_exit.signature)
  1035      # Initiate exit
  1036      initiate_validator_exit(state, voluntary_exit.validator_index)
  1037  ```