Skip to content

Gloas Light Client -- Sync Protocol

Introduction

This upgrade extends light client data to reflect the Gloas changes in how execution data is tracked in BeaconBlockBody. It extends the Electra Light Client specifications. The fork document explains how to upgrade existing Electra based deployments to Gloas.

Additional documents describes the impact of the upgrade on certain roles:

Types

Name SSZ equivalent Description
ExecutionBranch Vector[Bytes32, floorlog2(EXECUTION_BLOCK_HASH_GINDEX_GLOAS)] Merkle branch of signed_execution_payload_bid.message.parent_block_hash (post-Gloas) or execution_payload.block_hash within BeaconBlockBody

Constants

Frozen constants

Existing GeneralizedIndex constants are frozen at their Capella values.

Name Value
EXECUTION_PAYLOAD_GINDEX get_generalized_index(capella.BeaconBlockBody, 'execution_payload') (= 25)

New constants

Name Value
EXECUTION_BLOCK_HASH_GINDEX get_generalized_index(capella.BeaconBlockBody, 'execution_payload', 'block_hash') (= 412)
EXECUTION_BLOCK_HASH_GINDEX_DENEB get_generalized_index(deneb.BeaconBlockBody, 'execution_payload', 'block_hash') (= 812)
EXECUTION_BLOCK_HASH_GINDEX_GLOAS get_generalized_index(BeaconBlockBody, 'signed_execution_payload_bid', 'message', 'parent_block_hash') (= 832)

Containers

Modified LightClientHeader

1
2
3
4
5
6
7
8
class LightClientHeader(Container):
    beacon: BeaconBlockHeader
    # [Modified in Gloas:EIP7732]
    # Removed `execution`
    # [New in Gloas:EIP7732]
    execution_block_hash: Hash32
    # [Modified in Gloas:EIP7732]
    execution_branch: ExecutionBranch

Helpers

Modified get_lc_execution_root

def get_lc_execution_root(header: LightClientHeader) -> Root:
    epoch = compute_epoch_at_slot(header.beacon.slot)

    # [New in Gloas:EIP7732]
    if epoch >= GLOAS_FORK_EPOCH:
        return Root(header.execution_block_hash)

    # [Modified in Gloas:EIP7732]
    if epoch >= DENEB_FORK_EPOCH:
        if header.beacon.slot == GENESIS_SLOT:
            return hash_tree_root(deneb.ExecutionPayloadHeader())
        BLOCK_HASH_GINDEX = get_generalized_index(deneb.ExecutionPayloadHeader, "block_hash")
    elif epoch >= CAPELLA_FORK_EPOCH:
        if header.beacon.slot == GENESIS_SLOT:
            return hash_tree_root(capella.ExecutionPayloadHeader())
        BLOCK_HASH_GINDEX = get_generalized_index(capella.ExecutionPayloadHeader, "block_hash")
    else:
        return Root()

    # [Modified in Gloas:EIP7732]
    inner = header.execution_branch[
        : len(header.execution_branch) - floorlog2(EXECUTION_PAYLOAD_GINDEX)
    ]
    return compute_merkle_branch_root(
        leaf=Bytes32(header.execution_block_hash),
        branch=inner[len(inner) - floorlog2(BLOCK_HASH_GINDEX) :],
        depth=floorlog2(BLOCK_HASH_GINDEX),
        index=get_subtree_index(BLOCK_HASH_GINDEX),
    )

Modified is_valid_light_client_header

def is_valid_light_client_header(header: LightClientHeader) -> bool:
    epoch = compute_epoch_at_slot(header.beacon.slot)

    # [New in Gloas:EIP7732]
    if epoch >= GLOAS_FORK_EPOCH:
        return is_valid_normalized_merkle_branch(
            leaf=Bytes32(header.execution_block_hash),
            branch=header.execution_branch,
            gindex=EXECUTION_BLOCK_HASH_GINDEX_GLOAS,
            root=header.beacon.body_root,
        )

    # [Modified in Gloas:EIP7732]
    if epoch >= DENEB_FORK_EPOCH:
        return is_valid_normalized_merkle_branch(
            leaf=Bytes32(header.execution_block_hash),
            branch=header.execution_branch,
            gindex=EXECUTION_BLOCK_HASH_GINDEX_DENEB,
            root=header.beacon.body_root,
        )

    # [Modified in Gloas:EIP7732]
    if epoch >= CAPELLA_FORK_EPOCH:
        return is_valid_normalized_merkle_branch(
            leaf=Bytes32(header.execution_block_hash),
            branch=header.execution_branch,
            gindex=EXECUTION_BLOCK_HASH_GINDEX,
            root=header.beacon.body_root,
        )

    # [Modified in Gloas:EIP7732]
    return header.execution_block_hash == Hash32() and header.execution_branch == ExecutionBranch()