Add `block_to_light_client_header` helper

Introduce `block_to_light_client_header` helper function to enable
future forks to override it with additional info (e.g., execution),
without having to change the general light client logic.

Likewise, update existing light client data creation flow to use
`block_to_light_client_header` and default-initialize empty fields.

Furthermore, generalize `create_update` helper to streamline test code
using `block_to_light_client_header`.

Note: In Altair spec, LC header is the same as `BeaconBlockHeader`.
however; future forks will extend it with more information.
This commit is contained in:
Etan Kissling 2022-12-06 17:44:41 +01:00
parent 2a7083d3cd
commit 8bf801ecc6
No known key found for this signature in database
GPG Key ID: B21DA824C5A3D03D
4 changed files with 181 additions and 224 deletions

View File

@ -11,6 +11,7 @@
- [Introduction](#introduction)
- [Helper functions](#helper-functions)
- [`compute_merkle_proof_for_state`](#compute_merkle_proof_for_state)
- [`block_to_light_client_header`](#block_to_light_client_header)
- [Deriving light client data](#deriving-light-client-data)
- [`create_light_client_bootstrap`](#create_light_client_bootstrap)
- [`create_light_client_update`](#create_light_client_update)
@ -34,6 +35,19 @@ def compute_merkle_proof_for_state(state: BeaconState,
...
```
### `block_to_light_client_header`
```python
def block_to_light_client_header(block: SignedBeaconBlock) -> BeaconBlockHeader:
return BeaconBlockHeader(
slot=block.message.slot,
proposer_index=block.message.proposer_index,
parent_root=block.message.parent_root,
state_root=block.message.state_root,
body_root=hash_tree_root(block.message.body),
)
```
## Deriving light client data
Full nodes are expected to derive light client data from historic blocks and states and provide it to other clients.
@ -55,13 +69,7 @@ def create_light_client_bootstrap(state: BeaconState,
assert hash_tree_root(header) == hash_tree_root(block.message)
return LightClientBootstrap(
header=BeaconBlockHeader(
slot=state.latest_block_header.slot,
proposer_index=state.latest_block_header.proposer_index,
parent_root=state.latest_block_header.parent_root,
state_root=hash_tree_root(state),
body_root=state.latest_block_header.body_root,
),
header=block_to_light_client_header(block),
current_sync_committee=state.current_sync_committee,
current_sync_committee_branch=compute_merkle_proof_for_state(state, CURRENT_SYNC_COMMITTEE_INDEX),
)
@ -103,42 +111,30 @@ def create_light_client_update(state: BeaconState,
assert hash_tree_root(attested_header) == hash_tree_root(attested_block.message) == block.message.parent_root
update_attested_period = compute_sync_committee_period_at_slot(attested_block.message.slot)
update = LightClientUpdate()
update.attested_header = block_to_light_client_header(attested_block)
# `next_sync_committee` is only useful if the message is signed by the current sync committee
if update_attested_period == update_signature_period:
next_sync_committee = attested_state.next_sync_committee
next_sync_committee_branch = compute_merkle_proof_for_state(attested_state, NEXT_SYNC_COMMITTEE_INDEX)
else:
next_sync_committee = SyncCommittee()
next_sync_committee_branch = [Bytes32() for _ in range(floorlog2(NEXT_SYNC_COMMITTEE_INDEX))]
update.next_sync_committee = attested_state.next_sync_committee
update.next_sync_committee_branch = \
compute_merkle_proof_for_state(attested_state, NEXT_SYNC_COMMITTEE_INDEX)
# Indicate finality whenever possible
if finalized_block is not None:
if finalized_block.message.slot != GENESIS_SLOT:
finalized_header = BeaconBlockHeader(
slot=finalized_block.message.slot,
proposer_index=finalized_block.message.proposer_index,
parent_root=finalized_block.message.parent_root,
state_root=finalized_block.message.state_root,
body_root=hash_tree_root(finalized_block.message.body),
)
assert hash_tree_root(finalized_header) == attested_state.finalized_checkpoint.root
update.finalized_header = block_to_light_client_header(finalized_block)
assert hash_tree_root(update.finalized_header) == attested_state.finalized_checkpoint.root
else:
assert attested_state.finalized_checkpoint.root == Bytes32()
finalized_header = BeaconBlockHeader()
finality_branch = compute_merkle_proof_for_state(attested_state, FINALIZED_ROOT_INDEX)
else:
finalized_header = BeaconBlockHeader()
finality_branch = [Bytes32() for _ in range(floorlog2(FINALIZED_ROOT_INDEX))]
update.finality_branch = \
compute_merkle_proof_for_state(attested_state, FINALIZED_ROOT_INDEX)
return LightClientUpdate(
attested_header=attested_header,
next_sync_committee=next_sync_committee,
next_sync_committee_branch=next_sync_committee_branch,
finalized_header=finalized_header,
finality_branch=finality_branch,
sync_aggregate=block.message.body.sync_aggregate,
signature_slot=block.message.slot,
)
update.sync_aggregate = block.message.body.sync_aggregate
update.signature_slot = block.message.slot
return update
```
Full nodes SHOULD provide the best derivable `LightClientUpdate` (according to `is_better_update`) for each sync committee period covering any epochs in range `[max(ALTAIR_FORK_EPOCH, current_epoch - MIN_EPOCHS_FOR_BLOCK_REQUESTS), current_epoch]` where `current_epoch` is defined by the current wall-clock time. Full nodes MAY also provide `LightClientUpdate` for other sync committee periods.

View File

@ -9,45 +9,23 @@ from eth2spec.test.helpers.attestations import (
)
from eth2spec.test.helpers.constants import MINIMAL
from eth2spec.test.helpers.light_client import (
get_sync_aggregate,
signed_block_to_header,
create_update,
)
from eth2spec.test.helpers.state import (
next_slots,
)
from math import floor
def create_update(spec, test, with_next, with_finality, participation_rate):
def create_test_update(spec, test, with_next, with_finality, participation_rate):
attested_state, attested_block, finalized_block = test
num_participants = floor(spec.SYNC_COMMITTEE_SIZE * participation_rate)
attested_header = signed_block_to_header(spec, attested_block)
if with_next:
next_sync_committee = attested_state.next_sync_committee
next_sync_committee_branch = spec.compute_merkle_proof_for_state(attested_state, spec.NEXT_SYNC_COMMITTEE_INDEX)
else:
next_sync_committee = spec.SyncCommittee()
next_sync_committee_branch = [spec.Bytes32() for _ in range(spec.floorlog2(spec.NEXT_SYNC_COMMITTEE_INDEX))]
if with_finality:
finalized_header = signed_block_to_header(spec, finalized_block)
finality_branch = spec.compute_merkle_proof_for_state(attested_state, spec.FINALIZED_ROOT_INDEX)
else:
finalized_header = spec.BeaconBlockHeader()
finality_branch = [spec.Bytes32() for _ in range(spec.floorlog2(spec.FINALIZED_ROOT_INDEX))]
sync_aggregate, signature_slot = get_sync_aggregate(spec, attested_state, num_participants)
return spec.LightClientUpdate(
attested_header=attested_header,
next_sync_committee=next_sync_committee,
next_sync_committee_branch=next_sync_committee_branch,
finalized_header=finalized_header,
finality_branch=finality_branch,
sync_aggregate=sync_aggregate,
signature_slot=signature_slot,
return create_update(
spec,
attested_state,
attested_block,
finalized_block,
with_next,
with_finality,
participation_rate,
)
@ -84,76 +62,76 @@ def test_update_ranking(spec, state):
# Create updates (in descending order of quality)
updates = [
# Updates with sync committee finality
create_update(spec, fin, with_next=1, with_finality=1, participation_rate=1.0),
create_update(spec, lat, with_next=1, with_finality=1, participation_rate=1.0),
create_update(spec, fin, with_next=1, with_finality=1, participation_rate=0.8),
create_update(spec, lat, with_next=1, with_finality=1, participation_rate=0.8),
create_test_update(spec, fin, with_next=1, with_finality=1, participation_rate=1.0),
create_test_update(spec, lat, with_next=1, with_finality=1, participation_rate=1.0),
create_test_update(spec, fin, with_next=1, with_finality=1, participation_rate=0.8),
create_test_update(spec, lat, with_next=1, with_finality=1, participation_rate=0.8),
# Updates without sync committee finality
create_update(spec, att, with_next=1, with_finality=1, participation_rate=1.0),
create_update(spec, att, with_next=1, with_finality=1, participation_rate=0.8),
create_test_update(spec, att, with_next=1, with_finality=1, participation_rate=1.0),
create_test_update(spec, att, with_next=1, with_finality=1, participation_rate=0.8),
# Updates without indication of any finality
create_update(spec, att, with_next=1, with_finality=0, participation_rate=1.0),
create_update(spec, fin, with_next=1, with_finality=0, participation_rate=1.0),
create_update(spec, lat, with_next=1, with_finality=0, participation_rate=1.0),
create_update(spec, att, with_next=1, with_finality=0, participation_rate=0.8),
create_update(spec, fin, with_next=1, with_finality=0, participation_rate=0.8),
create_update(spec, lat, with_next=1, with_finality=0, participation_rate=0.8),
create_test_update(spec, att, with_next=1, with_finality=0, participation_rate=1.0),
create_test_update(spec, fin, with_next=1, with_finality=0, participation_rate=1.0),
create_test_update(spec, lat, with_next=1, with_finality=0, participation_rate=1.0),
create_test_update(spec, att, with_next=1, with_finality=0, participation_rate=0.8),
create_test_update(spec, fin, with_next=1, with_finality=0, participation_rate=0.8),
create_test_update(spec, lat, with_next=1, with_finality=0, participation_rate=0.8),
# Updates with sync committee finality but no `next_sync_committee`
create_update(spec, sig, with_next=0, with_finality=1, participation_rate=1.0),
create_update(spec, fin, with_next=0, with_finality=1, participation_rate=1.0),
create_update(spec, lat, with_next=0, with_finality=1, participation_rate=1.0),
create_update(spec, sig, with_next=0, with_finality=1, participation_rate=0.8),
create_update(spec, fin, with_next=0, with_finality=1, participation_rate=0.8),
create_update(spec, lat, with_next=0, with_finality=1, participation_rate=0.8),
create_test_update(spec, sig, with_next=0, with_finality=1, participation_rate=1.0),
create_test_update(spec, fin, with_next=0, with_finality=1, participation_rate=1.0),
create_test_update(spec, lat, with_next=0, with_finality=1, participation_rate=1.0),
create_test_update(spec, sig, with_next=0, with_finality=1, participation_rate=0.8),
create_test_update(spec, fin, with_next=0, with_finality=1, participation_rate=0.8),
create_test_update(spec, lat, with_next=0, with_finality=1, participation_rate=0.8),
# Updates without sync committee finality and also no `next_sync_committee`
create_update(spec, att, with_next=0, with_finality=1, participation_rate=1.0),
create_update(spec, att, with_next=0, with_finality=1, participation_rate=0.8),
create_test_update(spec, att, with_next=0, with_finality=1, participation_rate=1.0),
create_test_update(spec, att, with_next=0, with_finality=1, participation_rate=0.8),
# Updates without indication of any finality nor `next_sync_committee`
create_update(spec, sig, with_next=0, with_finality=0, participation_rate=1.0),
create_update(spec, att, with_next=0, with_finality=0, participation_rate=1.0),
create_update(spec, fin, with_next=0, with_finality=0, participation_rate=1.0),
create_update(spec, lat, with_next=0, with_finality=0, participation_rate=1.0),
create_update(spec, sig, with_next=0, with_finality=0, participation_rate=0.8),
create_update(spec, att, with_next=0, with_finality=0, participation_rate=0.8),
create_update(spec, fin, with_next=0, with_finality=0, participation_rate=0.8),
create_update(spec, lat, with_next=0, with_finality=0, participation_rate=0.8),
create_test_update(spec, sig, with_next=0, with_finality=0, participation_rate=1.0),
create_test_update(spec, att, with_next=0, with_finality=0, participation_rate=1.0),
create_test_update(spec, fin, with_next=0, with_finality=0, participation_rate=1.0),
create_test_update(spec, lat, with_next=0, with_finality=0, participation_rate=1.0),
create_test_update(spec, sig, with_next=0, with_finality=0, participation_rate=0.8),
create_test_update(spec, att, with_next=0, with_finality=0, participation_rate=0.8),
create_test_update(spec, fin, with_next=0, with_finality=0, participation_rate=0.8),
create_test_update(spec, lat, with_next=0, with_finality=0, participation_rate=0.8),
# Updates with low sync committee participation
create_update(spec, fin, with_next=1, with_finality=1, participation_rate=0.4),
create_update(spec, lat, with_next=1, with_finality=1, participation_rate=0.4),
create_update(spec, att, with_next=1, with_finality=1, participation_rate=0.4),
create_update(spec, att, with_next=1, with_finality=0, participation_rate=0.4),
create_update(spec, fin, with_next=1, with_finality=0, participation_rate=0.4),
create_update(spec, lat, with_next=1, with_finality=0, participation_rate=0.4),
create_update(spec, sig, with_next=0, with_finality=1, participation_rate=0.4),
create_update(spec, fin, with_next=0, with_finality=1, participation_rate=0.4),
create_update(spec, lat, with_next=0, with_finality=1, participation_rate=0.4),
create_update(spec, att, with_next=0, with_finality=1, participation_rate=0.4),
create_update(spec, sig, with_next=0, with_finality=0, participation_rate=0.4),
create_update(spec, att, with_next=0, with_finality=0, participation_rate=0.4),
create_update(spec, fin, with_next=0, with_finality=0, participation_rate=0.4),
create_update(spec, lat, with_next=0, with_finality=0, participation_rate=0.4),
create_test_update(spec, fin, with_next=1, with_finality=1, participation_rate=0.4),
create_test_update(spec, lat, with_next=1, with_finality=1, participation_rate=0.4),
create_test_update(spec, att, with_next=1, with_finality=1, participation_rate=0.4),
create_test_update(spec, att, with_next=1, with_finality=0, participation_rate=0.4),
create_test_update(spec, fin, with_next=1, with_finality=0, participation_rate=0.4),
create_test_update(spec, lat, with_next=1, with_finality=0, participation_rate=0.4),
create_test_update(spec, sig, with_next=0, with_finality=1, participation_rate=0.4),
create_test_update(spec, fin, with_next=0, with_finality=1, participation_rate=0.4),
create_test_update(spec, lat, with_next=0, with_finality=1, participation_rate=0.4),
create_test_update(spec, att, with_next=0, with_finality=1, participation_rate=0.4),
create_test_update(spec, sig, with_next=0, with_finality=0, participation_rate=0.4),
create_test_update(spec, att, with_next=0, with_finality=0, participation_rate=0.4),
create_test_update(spec, fin, with_next=0, with_finality=0, participation_rate=0.4),
create_test_update(spec, lat, with_next=0, with_finality=0, participation_rate=0.4),
# Updates with very low sync committee participation
create_update(spec, fin, with_next=1, with_finality=1, participation_rate=0.2),
create_update(spec, lat, with_next=1, with_finality=1, participation_rate=0.2),
create_update(spec, att, with_next=1, with_finality=1, participation_rate=0.2),
create_update(spec, att, with_next=1, with_finality=0, participation_rate=0.2),
create_update(spec, fin, with_next=1, with_finality=0, participation_rate=0.2),
create_update(spec, lat, with_next=1, with_finality=0, participation_rate=0.2),
create_update(spec, sig, with_next=0, with_finality=1, participation_rate=0.2),
create_update(spec, fin, with_next=0, with_finality=1, participation_rate=0.2),
create_update(spec, lat, with_next=0, with_finality=1, participation_rate=0.2),
create_update(spec, att, with_next=0, with_finality=1, participation_rate=0.2),
create_update(spec, sig, with_next=0, with_finality=0, participation_rate=0.2),
create_update(spec, att, with_next=0, with_finality=0, participation_rate=0.2),
create_update(spec, fin, with_next=0, with_finality=0, participation_rate=0.2),
create_update(spec, lat, with_next=0, with_finality=0, participation_rate=0.2),
create_test_update(spec, fin, with_next=1, with_finality=1, participation_rate=0.2),
create_test_update(spec, lat, with_next=1, with_finality=1, participation_rate=0.2),
create_test_update(spec, att, with_next=1, with_finality=1, participation_rate=0.2),
create_test_update(spec, att, with_next=1, with_finality=0, participation_rate=0.2),
create_test_update(spec, fin, with_next=1, with_finality=0, participation_rate=0.2),
create_test_update(spec, lat, with_next=1, with_finality=0, participation_rate=0.2),
create_test_update(spec, sig, with_next=0, with_finality=1, participation_rate=0.2),
create_test_update(spec, fin, with_next=0, with_finality=1, participation_rate=0.2),
create_test_update(spec, lat, with_next=0, with_finality=1, participation_rate=0.2),
create_test_update(spec, att, with_next=0, with_finality=1, participation_rate=0.2),
create_test_update(spec, sig, with_next=0, with_finality=0, participation_rate=0.2),
create_test_update(spec, att, with_next=0, with_finality=0, participation_rate=0.2),
create_test_update(spec, fin, with_next=0, with_finality=0, participation_rate=0.2),
create_test_update(spec, lat, with_next=0, with_finality=0, participation_rate=0.2),
]
yield "updates", updates

View File

@ -11,43 +11,44 @@ from eth2spec.test.helpers.attestations import (
)
from eth2spec.test.helpers.constants import MINIMAL
from eth2spec.test.helpers.light_client import (
get_sync_aggregate,
initialize_light_client_store,
signed_block_to_header,
create_update,
)
from eth2spec.test.helpers.state import (
next_slots,
)
def setup_test(spec, state):
trusted_block = spec.SignedBeaconBlock()
trusted_block.message.state_root = state.hash_tree_root()
trusted_block_root = trusted_block.message.hash_tree_root()
bootstrap = spec.create_light_client_bootstrap(state, trusted_block)
store = spec.initialize_light_client_store(trusted_block_root, bootstrap)
store.next_sync_committee = state.next_sync_committee
return (trusted_block, store)
@with_altair_and_later
@spec_state_test_with_matching_config
def test_process_light_client_update_not_timeout(spec, state):
store = initialize_light_client_store(spec, state)
genesis_block, store = setup_test(spec, state)
# Block at slot 1 doesn't increase sync committee period, so it won't force update store.finalized_header
attested_block = state_transition_with_full_block(spec, state, False, False)
attested_header = signed_block_to_header(spec, attested_block)
# Sync committee signing the attested_header
sync_aggregate, signature_slot = get_sync_aggregate(spec, state)
next_sync_committee = spec.SyncCommittee()
next_sync_committee_branch = [spec.Bytes32() for _ in range(spec.floorlog2(spec.NEXT_SYNC_COMMITTEE_INDEX))]
signature_slot = state.slot + 1
# Ensure that finality checkpoint is genesis
assert state.finalized_checkpoint.epoch == 0
# Finality is unchanged
finalized_header = spec.BeaconBlockHeader()
finality_branch = [spec.Bytes32() for _ in range(spec.floorlog2(spec.FINALIZED_ROOT_INDEX))]
update = spec.LightClientUpdate(
attested_header=attested_header,
next_sync_committee=next_sync_committee,
next_sync_committee_branch=next_sync_committee_branch,
finalized_header=finalized_header,
finality_branch=finality_branch,
sync_aggregate=sync_aggregate,
signature_slot=signature_slot,
update = create_update(
spec,
attested_state=state,
attested_block=attested_block,
finalized_block=genesis_block,
with_next=False,
with_finality=False,
participation_rate=1.0,
)
pre_store = deepcopy(store)
@ -64,7 +65,7 @@ def test_process_light_client_update_not_timeout(spec, state):
@spec_state_test_with_matching_config
@with_presets([MINIMAL], reason="too slow")
def test_process_light_client_update_at_period_boundary(spec, state):
store = initialize_light_client_store(spec, state)
genesis_block, store = setup_test(spec, state)
# Forward to slot before next sync committee period so that next block is final one in period
next_slots(spec, state, spec.UPDATE_TIMEOUT - 2)
@ -73,25 +74,16 @@ def test_process_light_client_update_at_period_boundary(spec, state):
assert store_period == update_period
attested_block = state_transition_with_full_block(spec, state, False, False)
attested_header = signed_block_to_header(spec, attested_block)
signature_slot = state.slot + 1
# Sync committee signing the attested_header
sync_aggregate, signature_slot = get_sync_aggregate(spec, state)
next_sync_committee = spec.SyncCommittee()
next_sync_committee_branch = [spec.Bytes32() for _ in range(spec.floorlog2(spec.NEXT_SYNC_COMMITTEE_INDEX))]
# Finality is unchanged
finalized_header = spec.BeaconBlockHeader()
finality_branch = [spec.Bytes32() for _ in range(spec.floorlog2(spec.FINALIZED_ROOT_INDEX))]
update = spec.LightClientUpdate(
attested_header=attested_header,
next_sync_committee=next_sync_committee,
next_sync_committee_branch=next_sync_committee_branch,
finalized_header=finalized_header,
finality_branch=finality_branch,
sync_aggregate=sync_aggregate,
signature_slot=signature_slot,
update = create_update(
spec,
attested_state=state,
attested_block=attested_block,
finalized_block=genesis_block,
with_next=False,
with_finality=False,
participation_rate=1.0,
)
pre_store = deepcopy(store)
@ -108,7 +100,7 @@ def test_process_light_client_update_at_period_boundary(spec, state):
@spec_state_test_with_matching_config
@with_presets([MINIMAL], reason="too slow")
def test_process_light_client_update_timeout(spec, state):
store = initialize_light_client_store(spec, state)
genesis_block, store = setup_test(spec, state)
# Forward to next sync committee period
next_slots(spec, state, spec.UPDATE_TIMEOUT)
@ -117,26 +109,16 @@ def test_process_light_client_update_timeout(spec, state):
assert store_period + 1 == update_period
attested_block = state_transition_with_full_block(spec, state, False, False)
attested_header = signed_block_to_header(spec, attested_block)
signature_slot = state.slot + 1
# Sync committee signing the attested_header
sync_aggregate, signature_slot = get_sync_aggregate(spec, state)
# Sync committee is updated
next_sync_committee = state.next_sync_committee
next_sync_committee_branch = spec.compute_merkle_proof_for_state(state, spec.NEXT_SYNC_COMMITTEE_INDEX)
# Finality is unchanged
finalized_header = spec.BeaconBlockHeader()
finality_branch = [spec.Bytes32() for _ in range(spec.floorlog2(spec.FINALIZED_ROOT_INDEX))]
update = spec.LightClientUpdate(
attested_header=attested_header,
next_sync_committee=next_sync_committee,
next_sync_committee_branch=next_sync_committee_branch,
finalized_header=finalized_header,
finality_branch=finality_branch,
sync_aggregate=sync_aggregate,
signature_slot=signature_slot,
update = create_update(
spec,
attested_state=state,
attested_block=attested_block,
finalized_block=genesis_block,
with_next=True,
with_finality=False,
participation_rate=1.0,
)
pre_store = deepcopy(store)
@ -153,7 +135,7 @@ def test_process_light_client_update_timeout(spec, state):
@spec_state_test_with_matching_config
@with_presets([MINIMAL], reason="too slow")
def test_process_light_client_update_finality_updated(spec, state):
store = initialize_light_client_store(spec, state)
_, store = setup_test(spec, state)
# Change finality
blocks = []
@ -169,28 +151,21 @@ def test_process_light_client_update_finality_updated(spec, state):
assert store_period == update_period
attested_block = blocks[-1]
attested_header = signed_block_to_header(spec, attested_block)
signature_slot = state.slot + 1
# Sync committee signing the attested_header
sync_aggregate, signature_slot = get_sync_aggregate(spec, state)
# Updated sync_committee and finality
next_sync_committee = spec.SyncCommittee()
next_sync_committee_branch = [spec.Bytes32() for _ in range(spec.floorlog2(spec.NEXT_SYNC_COMMITTEE_INDEX))]
# Updated finality
finalized_block = blocks[spec.SLOTS_PER_EPOCH - 1]
finalized_header = signed_block_to_header(spec, finalized_block)
assert finalized_header.slot == spec.compute_start_slot_at_epoch(state.finalized_checkpoint.epoch)
assert finalized_header.hash_tree_root() == state.finalized_checkpoint.root
finality_branch = spec.compute_merkle_proof_for_state(state, spec.FINALIZED_ROOT_INDEX)
assert finalized_block.message.slot == spec.compute_start_slot_at_epoch(state.finalized_checkpoint.epoch)
assert finalized_block.message.hash_tree_root() == state.finalized_checkpoint.root
update = spec.LightClientUpdate(
attested_header=attested_header,
next_sync_committee=next_sync_committee,
next_sync_committee_branch=next_sync_committee_branch,
finalized_header=finalized_header,
finality_branch=finality_branch,
sync_aggregate=sync_aggregate,
signature_slot=signature_slot,
update = create_update(
spec,
attested_state=state,
attested_block=attested_block,
finalized_block=finalized_block,
with_next=False,
with_finality=True,
participation_rate=1.0,
)
spec.process_light_client_update(store, update, signature_slot, state.genesis_validators_root)

View File

@ -5,28 +5,7 @@ from eth2spec.test.helpers.sync_committee import (
compute_aggregate_sync_committee_signature,
compute_committee_indices,
)
def signed_block_to_header(spec, block):
return spec.BeaconBlockHeader(
slot=block.message.slot,
proposer_index=block.message.proposer_index,
parent_root=block.message.parent_root,
state_root=block.message.state_root,
body_root=block.message.body.hash_tree_root(),
)
def initialize_light_client_store(spec, state):
return spec.LightClientStore(
finalized_header=spec.BeaconBlockHeader(),
current_sync_committee=state.current_sync_committee,
next_sync_committee=state.next_sync_committee,
best_valid_update=None,
optimistic_header=spec.BeaconBlockHeader(),
previous_max_active_participants=0,
current_max_active_participants=0,
)
from math import floor
def get_sync_aggregate(spec, state, num_participants=None, signature_slot=None):
@ -60,3 +39,32 @@ def get_sync_aggregate(spec, state, num_participants=None, signature_slot=None):
sync_committee_signature=sync_committee_signature,
)
return sync_aggregate, signature_slot
def create_update(spec,
attested_state,
attested_block,
finalized_block,
with_next,
with_finality,
participation_rate):
num_participants = floor(spec.SYNC_COMMITTEE_SIZE * participation_rate)
update = spec.LightClientUpdate()
update.attested_header = spec.block_to_light_client_header(attested_block)
if with_next:
update.next_sync_committee = attested_state.next_sync_committee
update.next_sync_committee_branch = \
spec.compute_merkle_proof_for_state(attested_state, spec.NEXT_SYNC_COMMITTEE_INDEX)
if with_finality:
update.finalized_header = spec.block_to_light_client_header(finalized_block)
update.finality_branch = \
spec.compute_merkle_proof_for_state(attested_state, spec.FINALIZED_ROOT_INDEX)
update.sync_aggregate, update.signature_slot = \
get_sync_aggregate(spec, attested_state, num_participants)
return update