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:
parent
2a7083d3cd
commit
8bf801ecc6
|
@ -11,6 +11,7 @@
|
||||||
- [Introduction](#introduction)
|
- [Introduction](#introduction)
|
||||||
- [Helper functions](#helper-functions)
|
- [Helper functions](#helper-functions)
|
||||||
- [`compute_merkle_proof_for_state`](#compute_merkle_proof_for_state)
|
- [`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)
|
- [Deriving light client data](#deriving-light-client-data)
|
||||||
- [`create_light_client_bootstrap`](#create_light_client_bootstrap)
|
- [`create_light_client_bootstrap`](#create_light_client_bootstrap)
|
||||||
- [`create_light_client_update`](#create_light_client_update)
|
- [`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
|
## Deriving light client data
|
||||||
|
|
||||||
Full nodes are expected to derive light client data from historic blocks and states and provide it to other clients.
|
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)
|
assert hash_tree_root(header) == hash_tree_root(block.message)
|
||||||
|
|
||||||
return LightClientBootstrap(
|
return LightClientBootstrap(
|
||||||
header=BeaconBlockHeader(
|
header=block_to_light_client_header(block),
|
||||||
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,
|
|
||||||
),
|
|
||||||
current_sync_committee=state.current_sync_committee,
|
current_sync_committee=state.current_sync_committee,
|
||||||
current_sync_committee_branch=compute_merkle_proof_for_state(state, CURRENT_SYNC_COMMITTEE_INDEX),
|
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
|
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_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
|
# `next_sync_committee` is only useful if the message is signed by the current sync committee
|
||||||
if update_attested_period == update_signature_period:
|
if update_attested_period == update_signature_period:
|
||||||
next_sync_committee = attested_state.next_sync_committee
|
update.next_sync_committee = attested_state.next_sync_committee
|
||||||
next_sync_committee_branch = compute_merkle_proof_for_state(attested_state, NEXT_SYNC_COMMITTEE_INDEX)
|
update.next_sync_committee_branch = \
|
||||||
else:
|
compute_merkle_proof_for_state(attested_state, NEXT_SYNC_COMMITTEE_INDEX)
|
||||||
next_sync_committee = SyncCommittee()
|
|
||||||
next_sync_committee_branch = [Bytes32() for _ in range(floorlog2(NEXT_SYNC_COMMITTEE_INDEX))]
|
|
||||||
|
|
||||||
# Indicate finality whenever possible
|
# Indicate finality whenever possible
|
||||||
if finalized_block is not None:
|
if finalized_block is not None:
|
||||||
if finalized_block.message.slot != GENESIS_SLOT:
|
if finalized_block.message.slot != GENESIS_SLOT:
|
||||||
finalized_header = BeaconBlockHeader(
|
update.finalized_header = block_to_light_client_header(finalized_block)
|
||||||
slot=finalized_block.message.slot,
|
assert hash_tree_root(update.finalized_header) == attested_state.finalized_checkpoint.root
|
||||||
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
|
|
||||||
else:
|
else:
|
||||||
assert attested_state.finalized_checkpoint.root == Bytes32()
|
assert attested_state.finalized_checkpoint.root == Bytes32()
|
||||||
finalized_header = BeaconBlockHeader()
|
update.finality_branch = \
|
||||||
finality_branch = compute_merkle_proof_for_state(attested_state, FINALIZED_ROOT_INDEX)
|
compute_merkle_proof_for_state(attested_state, FINALIZED_ROOT_INDEX)
|
||||||
else:
|
|
||||||
finalized_header = BeaconBlockHeader()
|
|
||||||
finality_branch = [Bytes32() for _ in range(floorlog2(FINALIZED_ROOT_INDEX))]
|
|
||||||
|
|
||||||
return LightClientUpdate(
|
update.sync_aggregate = block.message.body.sync_aggregate
|
||||||
attested_header=attested_header,
|
update.signature_slot = block.message.slot
|
||||||
next_sync_committee=next_sync_committee,
|
|
||||||
next_sync_committee_branch=next_sync_committee_branch,
|
return update
|
||||||
finalized_header=finalized_header,
|
|
||||||
finality_branch=finality_branch,
|
|
||||||
sync_aggregate=block.message.body.sync_aggregate,
|
|
||||||
signature_slot=block.message.slot,
|
|
||||||
)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
|
@ -9,45 +9,23 @@ from eth2spec.test.helpers.attestations import (
|
||||||
)
|
)
|
||||||
from eth2spec.test.helpers.constants import MINIMAL
|
from eth2spec.test.helpers.constants import MINIMAL
|
||||||
from eth2spec.test.helpers.light_client import (
|
from eth2spec.test.helpers.light_client import (
|
||||||
get_sync_aggregate,
|
create_update,
|
||||||
signed_block_to_header,
|
|
||||||
)
|
)
|
||||||
from eth2spec.test.helpers.state import (
|
from eth2spec.test.helpers.state import (
|
||||||
next_slots,
|
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
|
attested_state, attested_block, finalized_block = test
|
||||||
num_participants = floor(spec.SYNC_COMMITTEE_SIZE * participation_rate)
|
return create_update(
|
||||||
|
spec,
|
||||||
attested_header = signed_block_to_header(spec, attested_block)
|
attested_state,
|
||||||
|
attested_block,
|
||||||
if with_next:
|
finalized_block,
|
||||||
next_sync_committee = attested_state.next_sync_committee
|
with_next,
|
||||||
next_sync_committee_branch = spec.compute_merkle_proof_for_state(attested_state, spec.NEXT_SYNC_COMMITTEE_INDEX)
|
with_finality,
|
||||||
else:
|
participation_rate,
|
||||||
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,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -84,76 +62,76 @@ def test_update_ranking(spec, state):
|
||||||
# Create updates (in descending order of quality)
|
# Create updates (in descending order of quality)
|
||||||
updates = [
|
updates = [
|
||||||
# Updates with sync committee finality
|
# Updates with sync committee finality
|
||||||
create_update(spec, fin, with_next=1, with_finality=1, participation_rate=1.0),
|
create_test_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_test_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_test_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, lat, with_next=1, with_finality=1, participation_rate=0.8),
|
||||||
|
|
||||||
# Updates without sync committee finality
|
# Updates without sync committee finality
|
||||||
create_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=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=0.8),
|
||||||
|
|
||||||
# Updates without indication of any finality
|
# Updates without indication of any finality
|
||||||
create_update(spec, att, with_next=1, with_finality=0, participation_rate=1.0),
|
create_test_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_test_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_test_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_test_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_test_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, lat, with_next=1, with_finality=0, participation_rate=0.8),
|
||||||
|
|
||||||
# Updates with sync committee finality but no `next_sync_committee`
|
# 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_test_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_test_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_test_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_test_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_test_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, lat, with_next=0, with_finality=1, participation_rate=0.8),
|
||||||
|
|
||||||
# Updates without sync committee finality and also no `next_sync_committee`
|
# 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_test_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=0.8),
|
||||||
|
|
||||||
# Updates without indication of any finality nor `next_sync_committee`
|
# 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_test_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_test_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_test_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_test_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_test_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_test_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_test_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, lat, with_next=0, with_finality=0, participation_rate=0.8),
|
||||||
|
|
||||||
# Updates with low sync committee participation
|
# Updates with low sync committee participation
|
||||||
create_update(spec, fin, with_next=1, with_finality=1, participation_rate=0.4),
|
create_test_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_test_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_test_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_test_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_test_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_test_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_test_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_test_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_test_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_test_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_test_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_test_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_test_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, lat, with_next=0, with_finality=0, participation_rate=0.4),
|
||||||
|
|
||||||
# Updates with very low sync committee participation
|
# Updates with very low sync committee participation
|
||||||
create_update(spec, fin, with_next=1, with_finality=1, participation_rate=0.2),
|
create_test_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_test_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_test_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_test_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_test_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_test_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_test_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_test_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_test_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_test_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_test_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_test_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_test_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, lat, with_next=0, with_finality=0, participation_rate=0.2),
|
||||||
]
|
]
|
||||||
yield "updates", updates
|
yield "updates", updates
|
||||||
|
|
||||||
|
|
|
@ -11,43 +11,44 @@ from eth2spec.test.helpers.attestations import (
|
||||||
)
|
)
|
||||||
from eth2spec.test.helpers.constants import MINIMAL
|
from eth2spec.test.helpers.constants import MINIMAL
|
||||||
from eth2spec.test.helpers.light_client import (
|
from eth2spec.test.helpers.light_client import (
|
||||||
get_sync_aggregate,
|
create_update,
|
||||||
initialize_light_client_store,
|
|
||||||
signed_block_to_header,
|
|
||||||
)
|
)
|
||||||
from eth2spec.test.helpers.state import (
|
from eth2spec.test.helpers.state import (
|
||||||
next_slots,
|
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
|
@with_altair_and_later
|
||||||
@spec_state_test_with_matching_config
|
@spec_state_test_with_matching_config
|
||||||
def test_process_light_client_update_not_timeout(spec, state):
|
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
|
# 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_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))]
|
|
||||||
|
|
||||||
# Ensure that finality checkpoint is genesis
|
# Ensure that finality checkpoint is genesis
|
||||||
assert state.finalized_checkpoint.epoch == 0
|
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(
|
update = create_update(
|
||||||
attested_header=attested_header,
|
spec,
|
||||||
next_sync_committee=next_sync_committee,
|
attested_state=state,
|
||||||
next_sync_committee_branch=next_sync_committee_branch,
|
attested_block=attested_block,
|
||||||
finalized_header=finalized_header,
|
finalized_block=genesis_block,
|
||||||
finality_branch=finality_branch,
|
with_next=False,
|
||||||
sync_aggregate=sync_aggregate,
|
with_finality=False,
|
||||||
signature_slot=signature_slot,
|
participation_rate=1.0,
|
||||||
)
|
)
|
||||||
|
|
||||||
pre_store = deepcopy(store)
|
pre_store = deepcopy(store)
|
||||||
|
@ -64,7 +65,7 @@ def test_process_light_client_update_not_timeout(spec, state):
|
||||||
@spec_state_test_with_matching_config
|
@spec_state_test_with_matching_config
|
||||||
@with_presets([MINIMAL], reason="too slow")
|
@with_presets([MINIMAL], reason="too slow")
|
||||||
def test_process_light_client_update_at_period_boundary(spec, state):
|
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
|
# 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)
|
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
|
assert store_period == update_period
|
||||||
|
|
||||||
attested_block = state_transition_with_full_block(spec, state, False, False)
|
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
|
update = create_update(
|
||||||
sync_aggregate, signature_slot = get_sync_aggregate(spec, state)
|
spec,
|
||||||
next_sync_committee = spec.SyncCommittee()
|
attested_state=state,
|
||||||
next_sync_committee_branch = [spec.Bytes32() for _ in range(spec.floorlog2(spec.NEXT_SYNC_COMMITTEE_INDEX))]
|
attested_block=attested_block,
|
||||||
|
finalized_block=genesis_block,
|
||||||
# Finality is unchanged
|
with_next=False,
|
||||||
finalized_header = spec.BeaconBlockHeader()
|
with_finality=False,
|
||||||
finality_branch = [spec.Bytes32() for _ in range(spec.floorlog2(spec.FINALIZED_ROOT_INDEX))]
|
participation_rate=1.0,
|
||||||
|
|
||||||
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,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
pre_store = deepcopy(store)
|
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
|
@spec_state_test_with_matching_config
|
||||||
@with_presets([MINIMAL], reason="too slow")
|
@with_presets([MINIMAL], reason="too slow")
|
||||||
def test_process_light_client_update_timeout(spec, state):
|
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
|
# Forward to next sync committee period
|
||||||
next_slots(spec, state, spec.UPDATE_TIMEOUT)
|
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
|
assert store_period + 1 == update_period
|
||||||
|
|
||||||
attested_block = state_transition_with_full_block(spec, state, False, False)
|
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
|
update = create_update(
|
||||||
sync_aggregate, signature_slot = get_sync_aggregate(spec, state)
|
spec,
|
||||||
|
attested_state=state,
|
||||||
# Sync committee is updated
|
attested_block=attested_block,
|
||||||
next_sync_committee = state.next_sync_committee
|
finalized_block=genesis_block,
|
||||||
next_sync_committee_branch = spec.compute_merkle_proof_for_state(state, spec.NEXT_SYNC_COMMITTEE_INDEX)
|
with_next=True,
|
||||||
# Finality is unchanged
|
with_finality=False,
|
||||||
finalized_header = spec.BeaconBlockHeader()
|
participation_rate=1.0,
|
||||||
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,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
pre_store = deepcopy(store)
|
pre_store = deepcopy(store)
|
||||||
|
@ -153,7 +135,7 @@ def test_process_light_client_update_timeout(spec, state):
|
||||||
@spec_state_test_with_matching_config
|
@spec_state_test_with_matching_config
|
||||||
@with_presets([MINIMAL], reason="too slow")
|
@with_presets([MINIMAL], reason="too slow")
|
||||||
def test_process_light_client_update_finality_updated(spec, state):
|
def test_process_light_client_update_finality_updated(spec, state):
|
||||||
store = initialize_light_client_store(spec, state)
|
_, store = setup_test(spec, state)
|
||||||
|
|
||||||
# Change finality
|
# Change finality
|
||||||
blocks = []
|
blocks = []
|
||||||
|
@ -169,28 +151,21 @@ def test_process_light_client_update_finality_updated(spec, state):
|
||||||
assert store_period == update_period
|
assert store_period == update_period
|
||||||
|
|
||||||
attested_block = blocks[-1]
|
attested_block = blocks[-1]
|
||||||
attested_header = signed_block_to_header(spec, attested_block)
|
signature_slot = state.slot + 1
|
||||||
|
|
||||||
# Sync committee signing the attested_header
|
# Updated finality
|
||||||
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))]
|
|
||||||
finalized_block = blocks[spec.SLOTS_PER_EPOCH - 1]
|
finalized_block = blocks[spec.SLOTS_PER_EPOCH - 1]
|
||||||
finalized_header = signed_block_to_header(spec, finalized_block)
|
assert finalized_block.message.slot == spec.compute_start_slot_at_epoch(state.finalized_checkpoint.epoch)
|
||||||
assert finalized_header.slot == spec.compute_start_slot_at_epoch(state.finalized_checkpoint.epoch)
|
assert finalized_block.message.hash_tree_root() == state.finalized_checkpoint.root
|
||||||
assert finalized_header.hash_tree_root() == state.finalized_checkpoint.root
|
|
||||||
finality_branch = spec.compute_merkle_proof_for_state(state, spec.FINALIZED_ROOT_INDEX)
|
|
||||||
|
|
||||||
update = spec.LightClientUpdate(
|
update = create_update(
|
||||||
attested_header=attested_header,
|
spec,
|
||||||
next_sync_committee=next_sync_committee,
|
attested_state=state,
|
||||||
next_sync_committee_branch=next_sync_committee_branch,
|
attested_block=attested_block,
|
||||||
finalized_header=finalized_header,
|
finalized_block=finalized_block,
|
||||||
finality_branch=finality_branch,
|
with_next=False,
|
||||||
sync_aggregate=sync_aggregate,
|
with_finality=True,
|
||||||
signature_slot=signature_slot,
|
participation_rate=1.0,
|
||||||
)
|
)
|
||||||
|
|
||||||
spec.process_light_client_update(store, update, signature_slot, state.genesis_validators_root)
|
spec.process_light_client_update(store, update, signature_slot, state.genesis_validators_root)
|
||||||
|
|
|
@ -5,28 +5,7 @@ from eth2spec.test.helpers.sync_committee import (
|
||||||
compute_aggregate_sync_committee_signature,
|
compute_aggregate_sync_committee_signature,
|
||||||
compute_committee_indices,
|
compute_committee_indices,
|
||||||
)
|
)
|
||||||
|
from math import floor
|
||||||
|
|
||||||
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,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def get_sync_aggregate(spec, state, num_participants=None, signature_slot=None):
|
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,
|
sync_committee_signature=sync_committee_signature,
|
||||||
)
|
)
|
||||||
return sync_aggregate, signature_slot
|
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
|
||||||
|
|
Loading…
Reference in New Issue