update light client to v1.1.10 spec (#3457)

Adopts the changes introduced in the v1.1.10 ETH consensus-specs:
- Introduces `is_finality_update` helper
- Ensures `optimistic_header` always >= `finalized_header`
- Updates spec references
This commit is contained in:
Etan Kissling 2022-03-03 14:03:08 +01:00 committed by GitHub
parent 4c01b77773
commit 47d7814518
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 23 additions and 17 deletions

View File

@ -51,7 +51,7 @@ const
TARGET_AGGREGATORS_PER_SYNC_SUBCOMMITTEE* = 16
SYNC_COMMITTEE_SUBNET_COUNT* = 4
# https://github.com/ethereum/consensus-specs/blob/v1.1.9/specs/altair/sync-protocol.md#constants
# https://github.com/ethereum/consensus-specs/blob/v1.1.10/specs/altair/sync-protocol.md#constants
# All of these indices are rooted in `BeaconState`.
# The first member (`genesis_time`) is 32, subsequent members +1 each.
# If there are ever more than 32 members in `BeaconState`, indices change!
@ -69,7 +69,7 @@ const
INACTIVITY_SCORE_BIAS* = 4
INACTIVITY_SCORE_RECOVERY_RATE* = 16
# https://github.com/ethereum/consensus-specs/blob/v1.1.9/specs/altair/sync-protocol.md#misc
# https://github.com/ethereum/consensus-specs/blob/v1.1.10/specs/altair/sync-protocol.md#misc
# MIN_SYNC_COMMITTEE_PARTICIPANTS defined in presets
UPDATE_TIMEOUT* = SLOTS_PER_EPOCH * EPOCHS_PER_SYNC_COMMITTEE_PERIOD
@ -157,7 +157,7 @@ type
### Modified/overloaded
# https://github.com/ethereum/consensus-specs/blob/v1.1.9/specs/altair/sync-protocol.md#lightclientupdate
# https://github.com/ethereum/consensus-specs/blob/v1.1.10/specs/altair/sync-protocol.md#lightclientupdate
LightClientUpdate* = object
attested_header*: BeaconBlockHeader ##\
## The beacon block header that is attested to by the sync committee
@ -177,7 +177,7 @@ type
fork_version*: Version ##\
## Fork version for the aggregate signature
# https://github.com/ethereum/consensus-specs/blob/v1.1.9/specs/altair/sync-protocol.md#lightclientstore
# https://github.com/ethereum/consensus-specs/blob/v1.1.10/specs/altair/sync-protocol.md#lightclientstore
LightClientStore* = object
finalized_header*: BeaconBlockHeader ##\
## Beacon block header that is finalized

View File

@ -475,7 +475,7 @@ func has_flag*(flags: ParticipationFlags, flag_index: int): bool =
let flag = ParticipationFlags(1'u8 shl flag_index)
(flags and flag) == flag
# https://github.com/ethereum/consensus-specs/blob/v1.1.9/specs/altair/sync-protocol.md#get_subtree_index
# https://github.com/ethereum/consensus-specs/blob/v1.1.10/specs/altair/sync-protocol.md#get_subtree_index
func get_subtree_index*(idx: GeneralizedIndex): uint64 =
doAssert idx > 0
uint64(idx mod (type(idx)(1) shl log2trunc(idx)))

View File

@ -12,24 +12,28 @@ import
datatypes/altair,
helpers
# https://github.com/ethereum/consensus-specs/blob/v1.1.9/specs/altair/sync-protocol.md#get_active_header
# https://github.com/ethereum/consensus-specs/blob/v1.1.10/specs/altair/sync-protocol.md#get_active_header
func is_finality_update(update: altair.LightClientUpdate): bool =
not update.finalized_header.isZeroMemory
# https://github.com/ethereum/consensus-specs/blob/v1.1.10/specs/altair/sync-protocol.md#get_active_header
func get_active_header(update: altair.LightClientUpdate): BeaconBlockHeader =
# The "active header" is the header that the update is trying to convince
# us to accept. If a finalized header is present, it's the finalized
# header, otherwise it's the attested header
if not update.finalized_header.isZeroMemory:
if update.is_finality_update:
update.finalized_header
else:
update.attested_header
# https://github.com/ethereum/consensus-specs/blob/v1.1.9/specs/altair/sync-protocol.md#get_safety_threshold
# https://github.com/ethereum/consensus-specs/blob/v1.1.10/specs/altair/sync-protocol.md#get_safety_threshold
func get_safety_threshold(store: LightClientStore): uint64 =
max(
store.previous_max_active_participants,
store.current_max_active_participants
) div 2
# https://github.com/ethereum/consensus-specs/blob/v1.1.9/specs/altair/sync-protocol.md#validate_light_client_update
# https://github.com/ethereum/consensus-specs/blob/v1.1.10/specs/altair/sync-protocol.md#validate_light_client_update
proc validate_light_client_update*(
store: LightClientStore,
update: altair.LightClientUpdate,
@ -51,7 +55,7 @@ proc validate_light_client_update*(
# Verify that the `finalized_header`, if present, actually is the finalized
# header saved in the state of the `attested header`
if update.finalized_header.isZeroMemory:
if not update.is_finality_update:
if not update.finality_branch.isZeroMemory:
return false
else:
@ -100,7 +104,7 @@ proc validate_light_client_update*(
blsFastAggregateVerify(
participant_pubkeys, signing_root.data, sync_aggregate.sync_committee_signature)
# https://github.com/ethereum/consensus-specs/blob/v1.1.9/specs/altair/sync-protocol.md#apply_light_client_update
# https://github.com/ethereum/consensus-specs/blob/v1.1.10/specs/altair/sync-protocol.md#apply_light_client_update
func apply_light_client_update(
store: var LightClientStore,
update: altair.LightClientUpdate) =
@ -112,8 +116,10 @@ func apply_light_client_update(
store.current_sync_committee = store.next_sync_committee
store.next_sync_committee = update.next_sync_committee
store.finalized_header = active_header
if store.finalized_header.slot > store.optimistic_header.slot:
store.optimistic_header = store.finalized_header
# https://github.com/ethereum/consensus-specs/blob/v1.1.9/specs/altair/sync-protocol.md#process_light_client_update
# https://github.com/ethereum/consensus-specs/blob/v1.1.10/specs/altair/sync-protocol.md#process_light_client_update
proc process_light_client_update*(
store: var LightClientStore,
update: altair.LightClientUpdate,
@ -147,7 +153,7 @@ proc process_light_client_update*(
# Update finalized header
if sum_sync_committee_bits * 3 >= len(sync_committee_bits) * 2 and
not update.finalized_header.isZeroMemory:
update.is_finality_update:
# Normal update through 2/3 threshold
apply_light_client_update(store, update)
store.best_valid_update = none(altair.LightClientUpdate)

View File

@ -74,7 +74,7 @@ let full_sync_committee_bits = block:
res.bytes.fill(byte.high)
res
# https://github.com/ethereum/consensus-specs/blob/v1.1.9/tests/core/pyspec/eth2spec/test/altair/unittests/test_sync_protocol.py#L24-L33
# https://github.com/ethereum/consensus-specs/blob/v1.1.10/tests/core/pyspec/eth2spec/test/helpers/light_client.py#L6-L15
func initialize_light_client_store(state: auto): LightClientStore =
LightClientStore(
finalized_header: BeaconBlockHeader(),
@ -94,7 +94,7 @@ suite "EF - Altair - Unittests - Sync protocol" & preset():
res
genesisState = newClone(initGenesisState(cfg = cfg))
# https://github.com/ethereum/consensus-specs/blob/v1.1.9/tests/core/pyspec/eth2spec/test/altair/unittests/test_sync_protocol.py#L36-L90
# https://github.com/ethereum/consensus-specs/blob/v1.1.10/tests/core/pyspec/eth2spec/test/altair/unittests/test_sync_protocol.py#L27-L69
test "test_process_light_client_update_not_timeout":
let forked = assignClone(genesisState[])
template state: untyped {.inject.} = forked[].altairData.data
@ -151,7 +151,7 @@ suite "EF - Altair - Unittests - Sync protocol" & preset():
store.finalized_header == pre_store_finalized_header
store.best_valid_update.get == update
# https://github.com/ethereum/consensus-specs/blob/v1.1.9/tests/core/pyspec/eth2spec/test/altair/unittests/test_sync_protocol.py#L93-L154
# https://github.com/ethereum/consensus-specs/blob/v1.1.10/tests/core/pyspec/eth2spec/test/altair/unittests/test_sync_protocol.py#L72-L121
test "process_light_client_update_timeout":
let forked = assignClone(genesisState[])
template state: untyped {.inject.} = forked[].altairData.data
@ -215,7 +215,7 @@ suite "EF - Altair - Unittests - Sync protocol" & preset():
store.finalized_header == pre_store_finalized_header
store.best_valid_update.get == update
# https://github.com/ethereum/consensus-specs/blob/v1.1.9/tests/core/pyspec/eth2spec/test/altair/unittests/test_sync_protocol.py#L157-L224
# https://github.com/ethereum/consensus-specs/blob/v1.1.10/tests/core/pyspec/eth2spec/test/altair/unittests/test_sync_protocol.py#L124-L179
test "process_light_client_update_finality_updated":
let forked = assignClone(genesisState[])
template state: untyped {.inject.} = forked[].altairData.data