# Deneb -- The Beacon Chain **Notice**: This document is a work-in-progress for researchers and implementers. ## Table of contents - [Introduction](#introduction) - [Preset](#preset) - [Configuration](#configuration) - [Containers](#containers) - [Helpers](#helpers) - [Modified `get_attestation_participation_flag_indicies`](#modified-get_attestation_participation_flag_indicies) - [Beacon chain state transition function](#beacon-chain-state-transition-function) - [Block processing](#block-processing) - [Modified `process_attestation`](#modified-process_attestation) - [Testing](#testing) ## Introduction This feature allows for inclusion of attestations created during epoch `N` to be included in slots from epoch `N` as well as all slots in epoch `N+1` rather than the current `SLOTS_PER_EPOCH` slot restricted range. This is an extension of the Deneb upgrade. ## Preset ## Configuration ## Containers ## Helpers ### Modified `get_attestation_participation_flag_indicies` *Note:* The function `get_attestation_participation_flag_indicies` is modified to set the `TIMELY_TARGET_FLAG` for any correct target attestation, regardless of `inclusion_delay` as a baseline reward for any speed of inclusion of an attestation that contributes to justification of the contained chain. ```python def get_attestation_participation_flag_indices(state: BeaconState, data: AttestationData, inclusion_delay: uint64) -> Sequence[int]: """ Return the flag indices that are satisfied by an attestation. """ if data.target.epoch == get_current_epoch(state): justified_checkpoint = state.current_justified_checkpoint else: justified_checkpoint = state.previous_justified_checkpoint # Matching roots is_matching_source = data.source == justified_checkpoint is_matching_target = is_matching_source and data.target.root == get_block_root(state, data.target.epoch) is_matching_head = is_matching_target and data.beacon_block_root == get_block_root_at_slot(state, data.slot) assert is_matching_source participation_flag_indices = [] if is_matching_source and inclusion_delay <= integer_squareroot(SLOTS_PER_EPOCH): participation_flag_indices.append(TIMELY_SOURCE_FLAG_INDEX) if is_matching_target: # [Modified in EIP7045] participation_flag_indices.append(TIMELY_TARGET_FLAG_INDEX) if is_matching_head and inclusion_delay == MIN_ATTESTATION_INCLUSION_DELAY: participation_flag_indices.append(TIMELY_HEAD_FLAG_INDEX) return participation_flag_indices ``` ## Beacon chain state transition function ### Block processing #### Modified `process_attestation` *Note*: The function `process_attestation` is modified to expand valid slots for inclusion to those in both `target.epoch` epoch and `target.epoch + 1` epoch. Additionally, it utilizes an updated version of `get_attestation_participation_flag_indices` to ensure rewards are available for the extended attestation inclusion range. ```python def process_attestation(state: BeaconState, attestation: Attestation) -> None: data = attestation.data assert data.target.epoch in (get_previous_epoch(state), get_current_epoch(state)) assert data.target.epoch == compute_epoch_at_slot(data.slot) assert data.slot + MIN_ATTESTATION_INCLUSION_DELAY <= state.slot # [Modified in EIP7045] assert data.index < get_committee_count_per_slot(state, data.target.epoch) committee = get_beacon_committee(state, data.slot, data.index) assert len(attestation.aggregation_bits) == len(committee) # Participation flag indices participation_flag_indices = get_attestation_participation_flag_indices(state, data, state.slot - data.slot) # Verify signature assert is_valid_indexed_attestation(state, get_indexed_attestation(state, attestation)) # Update epoch participation flags if data.target.epoch == get_current_epoch(state): epoch_participation = state.current_epoch_participation else: epoch_participation = state.previous_epoch_participation proposer_reward_numerator = 0 for index in get_attesting_indices(state, data, attestation.aggregation_bits): for flag_index, weight in enumerate(PARTICIPATION_FLAG_WEIGHTS): if flag_index in participation_flag_indices and not has_flag(epoch_participation[index], flag_index): epoch_participation[index] = add_flag(epoch_participation[index], flag_index) proposer_reward_numerator += get_base_reward(state, index) * weight # Reward proposer proposer_reward_denominator = (WEIGHT_DENOMINATOR - PROPOSER_WEIGHT) * WEIGHT_DENOMINATOR // PROPOSER_WEIGHT proposer_reward = Gwei(proposer_reward_numerator // proposer_reward_denominator) increase_balance(state, get_beacon_proposer_index(state), proposer_reward) ``` ## Testing *Note*: The function `initialize_beacon_state_from_eth1` is modified for pure EIP7045 testing only. Modifications include: 1. Use `EIP7045_FORK_VERSION` as the previous and current fork version. ```python def initialize_beacon_state_from_eth1(eth1_block_hash: Hash32, eth1_timestamp: uint64, deposits: Sequence[Deposit], execution_payload_header: ExecutionPayloadHeader=ExecutionPayloadHeader() ) -> BeaconState: fork = Fork( previous_version=EIP7045_FORK_VERSION, # [Modified in EIP7045] for testing only current_version=EIP7045_FORK_VERSION, # [Modified in EIP7045] epoch=GENESIS_EPOCH, ) state = BeaconState( genesis_time=eth1_timestamp + GENESIS_DELAY, fork=fork, eth1_data=Eth1Data(block_hash=eth1_block_hash, deposit_count=uint64(len(deposits))), latest_block_header=BeaconBlockHeader(body_root=hash_tree_root(BeaconBlockBody())), randao_mixes=[eth1_block_hash] * EPOCHS_PER_HISTORICAL_VECTOR, # Seed RANDAO with Eth1 entropy ) # Process deposits leaves = list(map(lambda deposit: deposit.data, deposits)) for index, deposit in enumerate(deposits): deposit_data_list = List[DepositData, 2**DEPOSIT_CONTRACT_TREE_DEPTH](*leaves[:index + 1]) state.eth1_data.deposit_root = hash_tree_root(deposit_data_list) process_deposit(state, deposit) # Process activations for index, validator in enumerate(state.validators): balance = state.balances[index] validator.effective_balance = min(balance - balance % EFFECTIVE_BALANCE_INCREMENT, MAX_EFFECTIVE_BALANCE) if validator.effective_balance == MAX_EFFECTIVE_BALANCE: validator.activation_eligibility_epoch = GENESIS_EPOCH validator.activation_epoch = GENESIS_EPOCH # Set genesis validators root for domain separation and chain versioning state.genesis_validators_root = hash_tree_root(state.validators) # Fill in sync committees # Note: A duplicate committee is assigned for the current and next committee at genesis state.current_sync_committee = get_next_sync_committee(state) state.next_sync_committee = get_next_sync_committee(state) # Initialize the execution payload header state.latest_execution_payload_header = execution_payload_header return state ```