Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add LightClient(Finality|Optimistic)Update #2944

Merged
merged 2 commits into from
Jul 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions specs/altair/light-client/full-node.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
- [Deriving light client data](#deriving-light-client-data)
- [`create_light_client_bootstrap`](#create_light_client_bootstrap)
- [`create_light_client_update`](#create_light_client_update)
- [`create_light_client_finality_update`](#create_light_client_finality_update)
- [`create_light_client_optimistic_update`](#create_light_client_optimistic_update)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->
<!-- /TOC -->
Expand Down Expand Up @@ -133,3 +135,31 @@ Full nodes SHOULD provide the best derivable `LightClientUpdate` (according to `
- `LightClientUpdate` are assigned to sync committee periods based on their `attested_header.slot`
- `LightClientUpdate` are only considered if `compute_sync_committee_period(compute_epoch_at_slot(update.attested_header.slot)) == compute_sync_committee_period(compute_epoch_at_slot(update.signature_slot))`
- Only `LightClientUpdate` with `next_sync_committee` as selected by fork choice are provided, regardless of ranking by `is_better_update`. To uniquely identify a non-finalized sync committee fork, all of `period`, `current_sync_committee` and `next_sync_committee` need to be incorporated, as sync committees may reappear over time.

### `create_light_client_finality_update`

```python
def create_light_client_finality_update(update: LightClientUpdate) -> LightClientFinalityUpdate:
return LightClientFinalityUpdate(
attested_header=update.attested_header,
finalized_header=update.finalized_header,
finality_branch=update.finality_branch,
sync_aggregate=update.sync_aggregate,
signature_slot=update.signature_slot,
)
```

Full nodes SHOULD provide the `LightClientFinalityUpdate` with the highest `attested_header.slot` (if multiple, highest `signature_slot`) as selected by fork choice, and SHOULD support a push mechanism to deliver new `LightClientFinalityUpdate` whenever `finalized_header` changes.

### `create_light_client_optimistic_update`

```python
def create_light_client_optimistic_update(update: LightClientUpdate) -> LightClientOptimisticUpdate:
return LightClientOptimisticUpdate(
attested_header=update.attested_header,
sync_aggregate=update.sync_aggregate,
signature_slot=update.signature_slot,
)
```

Full nodes SHOULD provide the `LightClientOptimisticUpdate` with the highest `attested_header.slot` (if multiple, highest `signature_slot`) as selected by fork choice, and SHOULD support a push mechanism to deliver new `LightClientOptimisticUpdate` whenever `attested_header` changes.
75 changes: 74 additions & 1 deletion specs/altair/light-client/sync-protocol.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
- [Containers](#containers)
- [`LightClientBootstrap`](#lightclientbootstrap)
- [`LightClientUpdate`](#lightclientupdate)
- [`LightClientFinalityUpdate`](#lightclientfinalityupdate)
- [`LightClientOptimisticUpdate`](#lightclientoptimisticupdate)
- [`LightClientStore`](#lightclientstore)
- [Helper functions](#helper-functions)
- [`is_sync_committee_update`](#is_sync_committee_update)
Expand All @@ -31,6 +33,8 @@
- [`validate_light_client_update`](#validate_light_client_update)
- [`apply_light_client_update`](#apply_light_client_update)
- [`process_light_client_update`](#process_light_client_update)
- [`process_light_client_finality_update`](#process_light_client_finality_update)
- [`process_light_client_optimistic_update`](#process_light_client_optimistic_update)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->
<!-- /TOC -->
Expand Down Expand Up @@ -96,6 +100,33 @@ class LightClientUpdate(Container):
signature_slot: Slot
```

### `LightClientFinalityUpdate`

```python
class LightClientFinalityUpdate(Container):
# The beacon block header that is attested to by the sync committee
attested_header: BeaconBlockHeader
# The finalized beacon block header attested to by Merkle branch
finalized_header: BeaconBlockHeader
finality_branch: Vector[Bytes32, floorlog2(FINALIZED_ROOT_INDEX)]
# Sync committee aggregate signature
sync_aggregate: SyncAggregate
# Slot at which the aggregate signature was created (untrusted)
signature_slot: Slot
```

### `LightClientOptimisticUpdate`

```python
class LightClientOptimisticUpdate(Container):
# The beacon block header that is attested to by the sync committee
attested_header: BeaconBlockHeader
# Sync committee aggregate signature
sync_aggregate: SyncAggregate
# Slot at which the aggregate signature was created (untrusted)
signature_slot: Slot
```

### `LightClientStore`

```python
Expand Down Expand Up @@ -250,7 +281,11 @@ def initialize_light_client_store(trusted_block_root: Root,

## Light client state updates

A light client receives `update` objects of type `LightClientUpdate`. Every `update` triggers `process_light_client_update(store, update, current_slot, genesis_validators_root)` where `current_slot` is the current slot based on a local clock. `process_slot_for_light_client_store` is triggered every time the current slot increments.
- A light client receives objects of type `LightClientUpdate`, `LightClientFinalityUpdate` and `LightClientOptimisticUpdate`:
- **`update: LightClientUpdate`**: Every `update` triggers `process_light_client_update(store, update, current_slot, genesis_validators_root)` where `current_slot` is the current slot based on a local clock.
- **`finality_update: LightClientFinalityUpdate`**: Every `finality_update` triggers `process_light_client_finality_update(store, finality_update, current_slot, genesis_validators_root)`.
- **`optimistic_update: LightClientOptimisticUpdate`**: Every `optimistic_update` triggers `process_light_client_optimistic_update(store, optimistic_update, current_slot, genesis_validators_root)`.
- `process_slot_for_light_client_store` is triggered every time the current slot increments.

### `process_slot_for_light_client_store`

Expand Down Expand Up @@ -420,3 +455,41 @@ def process_light_client_update(store: LightClientStore,
apply_light_client_update(store, update)
store.best_valid_update = None
```

### `process_light_client_finality_update`

```python
def process_light_client_finality_update(store: LightClientStore,
finality_update: LightClientFinalityUpdate,
current_slot: Slot,
genesis_validators_root: Root) -> None:
update = LightClientUpdate(
attested_header=finality_update.attested_header,
next_sync_committee=SyncCommittee(),
next_sync_committee_branch=[Bytes32() for _ in range(floorlog2(NEXT_SYNC_COMMITTEE_INDEX))],
finalized_header=finality_update.finalized_header,
finality_branch=finality_update.finality_branch,
sync_aggregate=finality_update.sync_aggregate,
signature_slot=finality_update.signature_slot,
)
process_light_client_update(store, update, current_slot, genesis_validators_root)
```

### `process_light_client_optimistic_update`

```python
def process_light_client_optimistic_update(store: LightClientStore,
optimistic_update: LightClientOptimisticUpdate,
current_slot: Slot,
genesis_validators_root: Root) -> None:
update = LightClientUpdate(
attested_header=optimistic_update.attested_header,
next_sync_committee=SyncCommittee(),
next_sync_committee_branch=[Bytes32() for _ in range(floorlog2(NEXT_SYNC_COMMITTEE_INDEX))],
finalized_header=BeaconBlockHeader(),
finality_branch=[Bytes32() for _ in range(floorlog2(FINALIZED_ROOT_INDEX))],
sync_aggregate=optimistic_update.sync_aggregate,
signature_slot=optimistic_update.signature_slot,
)
process_light_client_update(store, update, current_slot, genesis_validators_root)
```