Skip to content

Capella Light Client -- Sync Protocol

Introduction

This upgrade adds information about the execution payload to light client data as part of the Capella upgrade. It extends the Altair Light Client specifications. The fork document explains how to upgrade existing Altair based deployments to Capella.

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

Custom types

Name SSZ equivalent Description
ExecutionBranch Vector[Bytes32, floorlog2(EXECUTION_PAYLOAD_GINDEX)] Merkle branch of execution_payload within BeaconBlockBody

Constants

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

Containers

Modified LightClientHeader

1
2
3
4
5
6
class LightClientHeader(Container):
    beacon: BeaconBlockHeader
    # [New in Capella]
    execution: ExecutionPayloadHeader
    # [New in Capella]
    execution_branch: ExecutionBranch

Modified LightClientBootstrap

1
2
3
4
5
class LightClientBootstrap(Container):
    # [Modified in Capella]
    header: LightClientHeader
    current_sync_committee: SyncCommittee
    current_sync_committee_branch: CurrentSyncCommitteeBranch

Modified LightClientUpdate

class LightClientUpdate(Container):
    # [Modified in Capella]
    attested_header: LightClientHeader
    next_sync_committee: SyncCommittee
    next_sync_committee_branch: NextSyncCommitteeBranch
    # [Modified in Capella]
    finalized_header: LightClientHeader
    finality_branch: FinalityBranch
    sync_aggregate: SyncAggregate
    signature_slot: Slot

Modified LightClientFinalityUpdate

1
2
3
4
5
6
7
8
class LightClientFinalityUpdate(Container):
    # [Modified in Capella]
    attested_header: LightClientHeader
    # [Modified in Capella]
    finalized_header: LightClientHeader
    finality_branch: FinalityBranch
    sync_aggregate: SyncAggregate
    signature_slot: Slot

Modified LightClientOptimisticUpdate

1
2
3
4
5
class LightClientOptimisticUpdate(Container):
    # [Modified in Capella]
    attested_header: LightClientHeader
    sync_aggregate: SyncAggregate
    signature_slot: Slot

Modified LightClientStore

@dataclass
class LightClientStore(object):
    # [Modified in Capella]
    finalized_header: LightClientHeader
    current_sync_committee: SyncCommittee
    next_sync_committee: SyncCommittee
    # [Modified in Capella]
    best_valid_update: Optional[LightClientUpdate]
    # [Modified in Capella]
    optimistic_header: LightClientHeader
    previous_max_active_participants: uint64
    current_max_active_participants: uint64

Helper functions

get_lc_execution_root

1
2
3
4
5
6
7
def get_lc_execution_root(header: LightClientHeader) -> Root:
    epoch = compute_epoch_at_slot(header.beacon.slot)

    if epoch >= CAPELLA_FORK_EPOCH:
        return hash_tree_root(header.execution)

    return Root()

Modified is_valid_light_client_header

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

    if epoch < CAPELLA_FORK_EPOCH:
        return (
            header.execution == ExecutionPayloadHeader()
            and header.execution_branch == ExecutionBranch()
        )

    return is_valid_merkle_branch(
        leaf=get_lc_execution_root(header),
        branch=header.execution_branch,
        depth=floorlog2(EXECUTION_PAYLOAD_GINDEX),
        index=get_subtree_index(EXECUTION_PAYLOAD_GINDEX),
        root=header.beacon.body_root,
    )