Skip to content

Commit

Permalink
Merge pull request #2944 from etan-status/lc-reducedupdates
Browse files Browse the repository at this point in the history
Add `LightClient(Finality|Optimistic)Update`
  • Loading branch information
hwwhww authored Jul 21, 2022
2 parents 1d2ef9f + 95019bb commit 78b035a
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 1 deletion.
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)
```

0 comments on commit 78b035a

Please sign in to comment.