mirror of
https://github.com/ethereum/consensus-specs.git
synced 2026-02-01 13:24:58 -05:00
Merge pull request #2947 from etan-status/lc-forceupdate
Manually trigger `LightClientStore` force updates
This commit is contained in:
@@ -29,9 +29,9 @@
|
||||
- [Light client initialization](#light-client-initialization)
|
||||
- [`initialize_light_client_store`](#initialize_light_client_store)
|
||||
- [Light client state updates](#light-client-state-updates)
|
||||
- [`process_slot_for_light_client_store`](#process_slot_for_light_client_store)
|
||||
- [`validate_light_client_update`](#validate_light_client_update)
|
||||
- [`apply_light_client_update`](#apply_light_client_update)
|
||||
- [`process_light_client_store_force_update`](#process_light_client_store_force_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)
|
||||
@@ -285,28 +285,7 @@ def initialize_light_client_store(trusted_block_root: Root,
|
||||
- **`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`
|
||||
|
||||
```python
|
||||
def process_slot_for_light_client_store(store: LightClientStore, current_slot: Slot) -> None:
|
||||
if current_slot % UPDATE_TIMEOUT == 0:
|
||||
store.previous_max_active_participants = store.current_max_active_participants
|
||||
store.current_max_active_participants = 0
|
||||
if (
|
||||
current_slot > store.finalized_header.slot + UPDATE_TIMEOUT
|
||||
and store.best_valid_update is not None
|
||||
):
|
||||
# Forced best update when the update timeout has elapsed.
|
||||
# Because the apply logic waits for `finalized_header.slot` to indicate sync committee finality,
|
||||
# the `attested_header` may be treated as `finalized_header` in extended periods of non-finality
|
||||
# to guarantee progression into later sync committee periods according to `is_better_update`.
|
||||
if store.best_valid_update.finalized_header.slot <= store.finalized_header.slot:
|
||||
store.best_valid_update.finalized_header = store.best_valid_update.attested_header
|
||||
apply_light_client_update(store, store.best_valid_update)
|
||||
store.best_valid_update = None
|
||||
```
|
||||
- `process_light_client_store_force_update` MAY be called based on use case dependent heuristics if light client sync appears stuck.
|
||||
|
||||
### `validate_light_client_update`
|
||||
|
||||
@@ -399,12 +378,32 @@ def apply_light_client_update(store: LightClientStore, update: LightClientUpdate
|
||||
elif update_finalized_period == store_period + 1:
|
||||
store.current_sync_committee = store.next_sync_committee
|
||||
store.next_sync_committee = update.next_sync_committee
|
||||
store.previous_max_active_participants = store.current_max_active_participants
|
||||
store.current_max_active_participants = 0
|
||||
if update.finalized_header.slot > store.finalized_header.slot:
|
||||
store.finalized_header = update.finalized_header
|
||||
if store.finalized_header.slot > store.optimistic_header.slot:
|
||||
store.optimistic_header = store.finalized_header
|
||||
```
|
||||
|
||||
### `process_light_client_store_force_update`
|
||||
|
||||
```python
|
||||
def process_light_client_store_force_update(store: LightClientStore, current_slot: Slot) -> None:
|
||||
if (
|
||||
current_slot > store.finalized_header.slot + UPDATE_TIMEOUT
|
||||
and store.best_valid_update is not None
|
||||
):
|
||||
# Forced best update when the update timeout has elapsed.
|
||||
# Because the apply logic waits for `finalized_header.slot` to indicate sync committee finality,
|
||||
# the `attested_header` may be treated as `finalized_header` in extended periods of non-finality
|
||||
# to guarantee progression into later sync committee periods according to `is_better_update`.
|
||||
if store.best_valid_update.finalized_header.slot <= store.finalized_header.slot:
|
||||
store.best_valid_update.finalized_header = store.best_valid_update.attested_header
|
||||
apply_light_client_update(store, store.best_valid_update)
|
||||
store.best_valid_update = None
|
||||
```
|
||||
|
||||
### `process_light_client_update`
|
||||
|
||||
```python
|
||||
|
||||
@@ -72,13 +72,13 @@ def get_checks(store):
|
||||
}
|
||||
|
||||
|
||||
def emit_slot(test, spec, state):
|
||||
def emit_force_update(test, spec, state):
|
||||
current_slot = state.slot
|
||||
spec.process_slot_for_light_client_store(test.store, current_slot)
|
||||
spec.process_light_client_store_force_update(test.store, current_slot)
|
||||
|
||||
yield from [] # Consistently enable `yield from` syntax in calling tests
|
||||
test.steps.append({
|
||||
"process_slot": {
|
||||
"force_update": {
|
||||
"current_slot": int(current_slot),
|
||||
"checks": get_checks(test.store),
|
||||
}
|
||||
@@ -249,7 +249,7 @@ def test_light_client_sync(spec, state):
|
||||
# ```
|
||||
attested_state = state.copy()
|
||||
next_slots(spec, state, spec.UPDATE_TIMEOUT - 1)
|
||||
yield from emit_slot(test, spec, state)
|
||||
yield from emit_force_update(test, spec, state)
|
||||
assert test.store.finalized_header.slot == store_state.slot
|
||||
assert test.store.next_sync_committee == store_state.next_sync_committee
|
||||
assert test.store.best_valid_update is None
|
||||
@@ -293,7 +293,7 @@ def test_light_client_sync(spec, state):
|
||||
assert test.store.next_sync_committee == store_state.next_sync_committee
|
||||
assert test.store.best_valid_update == update
|
||||
assert test.store.optimistic_header.slot == attested_state.slot
|
||||
yield from emit_slot(test, spec, state)
|
||||
yield from emit_force_update(test, spec, state)
|
||||
assert test.store.finalized_header.slot == attested_state.slot
|
||||
assert test.store.next_sync_committee == attested_state.next_sync_committee
|
||||
assert test.store.best_valid_update is None
|
||||
|
||||
@@ -34,9 +34,9 @@ optimistic_header: {
|
||||
}
|
||||
```
|
||||
|
||||
#### `process_slot` execution step
|
||||
#### `force_update` execution step
|
||||
|
||||
The function `process_slot_for_light_client_store(store, current_slot)`
|
||||
The function `process_light_client_store_force_update(store, current_slot)`
|
||||
should be executed with the specified parameters:
|
||||
|
||||
```yaml
|
||||
|
||||
Reference in New Issue
Block a user