eth2.0-specs/specs/_features/eip7549/beacon-chain.md

5.9 KiB

EIP-7549 -- The Beacon Chain

Table of contents

Introduction

This is the beacon chain specification to move the attestation committee index outside of the signed message. For motivation, refer to EIP-7549.

Note: This specification is built upon Deneb and is under active development.

Preset

Name Value Description
MAX_ATTESTER_SLASHINGS_EIP7549 2**0 (= 1)
MAX_ATTESTATIONS_EIP7549 2**3 (= 8)

Containers

Modified containers

Attestation

class Attestation(Container):
    aggregation_bits: Bitlist[MAX_VALIDATORS_PER_COMMITTEE * MAX_COMMITTEES_PER_SLOT]  # [Modified in EIP7549]
    data: AttestationData
    committee_bits: Bitvector[MAX_COMMITTEES_PER_SLOT]  # [New in EIP7549]
    signature: BLSSignature

IndexedAttestation

class IndexedAttestation(Container):
    # [Modified in EIP7549]
    attesting_indices: List[ValidatorIndex, MAX_VALIDATORS_PER_COMMITTEE * MAX_COMMITTEES_PER_SLOT]
    data: AttestationData
    signature: BLSSignature

BeaconBlockBody

class BeaconBlockBody(Container):
    randao_reveal: BLSSignature
    eth1_data: Eth1Data  # Eth1 data vote
    graffiti: Bytes32  # Arbitrary data
    # Operations
    proposer_slashings: List[ProposerSlashing, MAX_PROPOSER_SLASHINGS]
    attester_slashings: List[AttesterSlashing, MAX_ATTESTER_SLASHINGS_EIP7549]  # [Modified in EIP7549]
    attestations: List[Attestation, MAX_ATTESTATIONS_EIP7549]  # [Modified in EIP7549]
    deposits: List[Deposit, MAX_DEPOSITS]
    voluntary_exits: List[SignedVoluntaryExit, MAX_VOLUNTARY_EXITS]
    sync_aggregate: SyncAggregate
    # Execution
    execution_payload: ExecutionPayload
    bls_to_execution_changes: List[SignedBLSToExecutionChange, MAX_BLS_TO_EXECUTION_CHANGES]
    blob_kzg_commitments: List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK]

Helper functions

Misc

get_committee_indices

def get_committee_indices(commitee_bits: Bitvector) -> Sequence[CommitteeIndex]:
    return [CommitteeIndex(index) for index, bit in enumerate(commitee_bits) if bit]

Beacon state accessors

Modified get_attesting_indices

def get_attesting_indices(state: BeaconState, attestation: Attestation) -> Set[ValidatorIndex]:
    """
    Return the set of attesting indices corresponding to ``aggregation_bits`` and ``committee_bits``.
    """
    output: Set[ValidatorIndex] = set()
    committee_indices = get_committee_indices(attestation.committee_bits)
    committee_offset = 0
    for index in committee_indices:
        committee = get_beacon_committee(state, attestation.data.slot, index)
        committee_attesters = set(
            index for i, index in enumerate(committee) if attestation.aggregation_bits[committee_offset + i])
        output = output.union(committee_attesters)

        committee_offset += len(committee)

    return output

Block processing

Modified process_attestation

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 EIP7549]
    assert data.index == 0
    committee_indices = get_committee_indices(attestation.committee_bits)
    participants_count = 0
    for index in committee_indices:
        assert index < get_committee_count_per_slot(state, data.target.epoch)
        committee = get_beacon_committee(state, data.slot, index)
        participants_count += len(committee)

    assert len(attestation.aggregation_bits) == participants_count

    # 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, attestation):
        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)