From ff0e525ecc7579db692267e8c47ed8fdf855d4a0 Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Fri, 28 Oct 2022 22:14:25 +0200 Subject: [PATCH] Pass blocks to LC data creation functions Future light client protocol extensions may include data from the block in addition to data from the state, e.g., `ExecutionPayloadHeader`. To prepare for this, also pass the block to the corresponding functions. In practice, blocks access is easier than historic state access, meaning there are no practical limitations due to this change. --- specs/altair/light-client/full-node.md | 21 +++- specs/altair/light-client/p2p-interface.md | 2 +- .../test/altair/light_client/test_sync.py | 64 ++++++---- .../light_client/test_update_ranking.py | 116 +++++++++--------- 4 files changed, 113 insertions(+), 90 deletions(-) diff --git a/specs/altair/light-client/full-node.md b/specs/altair/light-client/full-node.md index e3f4d7a3e..53ba4dc82 100644 --- a/specs/altair/light-client/full-node.md +++ b/specs/altair/light-client/full-node.md @@ -40,10 +40,19 @@ Full nodes are expected to derive light client data from historic blocks and sta ### `create_light_client_bootstrap` +To form a `LightClientBootstrap`, the following objects are needed: +- `state`: the post state of any post-Altair block +- `block`: the corresponding block + ```python -def create_light_client_bootstrap(state: BeaconState) -> LightClientBootstrap: +def create_light_client_bootstrap(state: BeaconState, + block: SignedBeaconBlock) -> LightClientBootstrap: assert compute_epoch_at_slot(state.slot) >= ALTAIR_FORK_EPOCH + assert state.slot == state.latest_block_header.slot + header = state.latest_block_header.copy() + header.state_root = hash_tree_root(state) + assert hash_tree_root(header) == hash_tree_root(block.message) return LightClientBootstrap( header=BeaconBlockHeader( @@ -54,7 +63,7 @@ def create_light_client_bootstrap(state: BeaconState) -> LightClientBootstrap: body_root=state.latest_block_header.body_root, ), 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), ) ``` @@ -69,13 +78,15 @@ Blocks are considered to be epoch boundary blocks if their block root can occur To form a `LightClientUpdate`, the following historical states and blocks are needed: - `state`: the post state of any block with a post-Altair parent block - `block`: the corresponding block -- `attested_state`: the post state of the block referred to by `block.parent_root` +- `attested_state`: the post state of `attested_block` +- `attested_block`: the block referred to by `block.parent_root` - `finalized_block`: the block referred to by `attested_state.finalized_checkpoint.root`, if locally available (may be unavailable, e.g., when using checkpoint sync, or if it was pruned locally) ```python def create_light_client_update(state: BeaconState, block: SignedBeaconBlock, attested_state: BeaconState, + attested_block: SignedBeaconBlock, finalized_block: Optional[SignedBeaconBlock]) -> LightClientUpdate: assert compute_epoch_at_slot(attested_state.slot) >= ALTAIR_FORK_EPOCH assert sum(block.message.body.sync_aggregate.sync_committee_bits) >= MIN_SYNC_COMMITTEE_PARTICIPANTS @@ -89,8 +100,8 @@ def create_light_client_update(state: BeaconState, assert attested_state.slot == attested_state.latest_block_header.slot attested_header = attested_state.latest_block_header.copy() attested_header.state_root = hash_tree_root(attested_state) - assert hash_tree_root(attested_header) == block.message.parent_root - update_attested_period = compute_sync_committee_period_at_slot(attested_header.slot) + 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) # `next_sync_committee` is only useful if the message is signed by the current sync committee if update_attested_period == update_signature_period: diff --git a/specs/altair/light-client/p2p-interface.md b/specs/altair/light-client/p2p-interface.md index 5c2b27b22..51b4759ba 100644 --- a/specs/altair/light-client/p2p-interface.md +++ b/specs/altair/light-client/p2p-interface.md @@ -116,7 +116,7 @@ Requests the `LightClientBootstrap` structure corresponding to a given post-Alta The request MUST be encoded as an SSZ-field. -Peers SHOULD provide results as defined in [`create_light_client_bootstrap`](./full-node.md#create_light_client_bootstrap). To fulfill a request, the requested block's post state needs to be known. +Peers SHOULD provide results as defined in [`create_light_client_bootstrap`](./full-node.md#create_light_client_bootstrap). To fulfill a request, the requested block and its post state need to be known. When a `LightClientBootstrap` instance cannot be produced for a given block root, peers SHOULD respond with error code `3: ResourceUnavailable`. diff --git a/tests/core/pyspec/eth2spec/test/altair/light_client/test_sync.py b/tests/core/pyspec/eth2spec/test/altair/light_client/test_sync.py index 4621a2772..1364c4bf1 100644 --- a/tests/core/pyspec/eth2spec/test/altair/light_client/test_sync.py +++ b/tests/core/pyspec/eth2spec/test/altair/light_client/test_sync.py @@ -35,7 +35,7 @@ def setup_test(spec, state): next_slots(spec, state, spec.SLOTS_PER_EPOCH * 2 - 1) trusted_block = state_transition_with_full_block(spec, state, True, True) trusted_block_root = trusted_block.message.hash_tree_root() - bootstrap = spec.create_light_client_bootstrap(state) + bootstrap = spec.create_light_client_bootstrap(state, trusted_block) yield "trusted_block_root", "meta", "0x" + trusted_block_root.hex() yield "bootstrap", bootstrap test.store = spec.initialize_light_client_store(trusted_block_root, bootstrap) @@ -85,9 +85,9 @@ def emit_force_update(test, spec, state): }) -def emit_update(test, spec, state, block, attested_state, finalized_block, with_next_sync_committee=True): - update = spec.create_light_client_update(state, block, attested_state, finalized_block) - if not with_next_sync_committee: +def emit_update(test, spec, state, block, attested_state, attested_block, finalized_block, with_next=True): + update = spec.create_light_client_update(state, block, attested_state, attested_block, finalized_block) + if not with_next: update.next_sync_committee = spec.SyncCommittee() update.next_sync_committee_branch = \ [spec.Bytes32() for _ in range(spec.floorlog2(spec.NEXT_SYNC_COMMITTEE_INDEX))] @@ -135,11 +135,12 @@ def test_light_client_sync(spec, state): next_slots(spec, state, spec.SLOTS_PER_EPOCH - 1) finalized_block = state_transition_with_full_block(spec, state, True, True) finalized_state = state.copy() - _, _, state = next_slots_with_attestations(spec, state, 2 * spec.SLOTS_PER_EPOCH, True, True) + _, _, state = next_slots_with_attestations(spec, state, 2 * spec.SLOTS_PER_EPOCH - 1, True, True) + attested_block = state_transition_with_full_block(spec, state, True, True) attested_state = state.copy() sync_aggregate, _ = get_sync_aggregate(spec, state) block = state_transition_with_full_block(spec, state, True, True, sync_aggregate=sync_aggregate) - yield from emit_update(test, spec, state, block, attested_state, finalized_block) + yield from emit_update(test, spec, state, block, attested_state, attested_block, finalized_block) assert test.store.finalized_header.slot == finalized_state.slot assert test.store.next_sync_committee == finalized_state.next_sync_committee assert test.store.best_valid_update is None @@ -160,11 +161,12 @@ def test_light_client_sync(spec, state): next_slots(spec, state, spec.SLOTS_PER_EPOCH - 1) finalized_block = state_transition_with_full_block(spec, state, True, True) finalized_state = state.copy() - _, _, state = next_slots_with_attestations(spec, state, 2 * spec.SLOTS_PER_EPOCH, True, True) + _, _, state = next_slots_with_attestations(spec, state, 2 * spec.SLOTS_PER_EPOCH - 1, True, True) + attested_block = state_transition_with_full_block(spec, state, True, True) attested_state = state.copy() sync_aggregate, _ = get_sync_aggregate(spec, state) block = state_transition_with_full_block(spec, state, True, True, sync_aggregate=sync_aggregate) - yield from emit_update(test, spec, state, block, attested_state, finalized_block) + yield from emit_update(test, spec, state, block, attested_state, attested_block, finalized_block) assert test.store.finalized_header.slot == finalized_state.slot assert test.store.next_sync_committee == finalized_state.next_sync_committee assert test.store.best_valid_update is None @@ -184,12 +186,13 @@ def test_light_client_sync(spec, state): next_slots(spec, state, spec.SLOTS_PER_EPOCH - 2) finalized_block = state_transition_with_full_block(spec, state, True, True) finalized_state = state.copy() - _, _, state = next_slots_with_attestations(spec, state, 2 * spec.SLOTS_PER_EPOCH, True, True) + _, _, state = next_slots_with_attestations(spec, state, 2 * spec.SLOTS_PER_EPOCH - 1, True, True) + attested_block = state_transition_with_full_block(spec, state, True, True) attested_state = state.copy() transition_to(spec, state, compute_start_slot_at_next_sync_committee_period(spec, state)) sync_aggregate, _ = get_sync_aggregate(spec, state) block = state_transition_with_full_block(spec, state, True, True, sync_aggregate=sync_aggregate) - yield from emit_update(test, spec, state, block, attested_state, finalized_block) + yield from emit_update(test, spec, state, block, attested_state, attested_block, finalized_block) assert test.store.finalized_header.slot == finalized_state.slot assert test.store.next_sync_committee == finalized_state.next_sync_committee assert test.store.best_valid_update is None @@ -206,10 +209,11 @@ def test_light_client_sync(spec, state): # sync committee # period boundary # ``` + attested_block = block.copy() attested_state = state.copy() sync_aggregate, _ = get_sync_aggregate(spec, state) block = state_transition_with_full_block(spec, state, True, True, sync_aggregate=sync_aggregate) - update = yield from emit_update(test, spec, state, block, attested_state, finalized_block=None) + update = yield from emit_update(test, spec, state, block, attested_state, attested_block, finalized_block=None) assert test.store.finalized_header.slot == finalized_state.slot assert test.store.next_sync_committee == finalized_state.next_sync_committee assert test.store.best_valid_update == update @@ -226,11 +230,12 @@ def test_light_client_sync(spec, state): # sync committee # period boundary # ``` + attested_block = block.copy() attested_state = state.copy() store_state = attested_state.copy() sync_aggregate, _ = get_sync_aggregate(spec, state) block = state_transition_with_full_block(spec, state, True, True, sync_aggregate=sync_aggregate) - update = yield from emit_update(test, spec, state, block, attested_state, finalized_block) + update = yield from emit_update(test, spec, state, block, attested_state, attested_block, finalized_block) assert test.store.finalized_header.slot == finalized_state.slot assert test.store.next_sync_committee == finalized_state.next_sync_committee assert test.store.best_valid_update == update @@ -247,6 +252,7 @@ def test_light_client_sync(spec, state): # sync committee `--- store.finalized_header # period boundary # ``` + attested_block = block.copy() attested_state = state.copy() next_slots(spec, state, spec.UPDATE_TIMEOUT - 1) yield from emit_force_update(test, spec, state) @@ -268,7 +274,7 @@ def test_light_client_sync(spec, state): # ``` sync_aggregate, _ = get_sync_aggregate(spec, state) block = state_transition_with_full_block(spec, state, True, True, sync_aggregate=sync_aggregate) - update = yield from emit_update(test, spec, state, block, attested_state, finalized_block=None) + update = yield from emit_update(test, spec, state, block, attested_state, attested_block, finalized_block=None) 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 == update @@ -285,10 +291,11 @@ def test_light_client_sync(spec, state): # sync committee sync committee # period boundary period boundary # ``` + attested_block = block.copy() attested_state = state.copy() sync_aggregate, _ = get_sync_aggregate(spec, state) block = state_transition_with_full_block(spec, state, True, True, sync_aggregate=sync_aggregate) - update = yield from emit_update(test, spec, state, block, attested_state, finalized_block) + update = yield from emit_update(test, spec, state, block, attested_state, attested_block, finalized_block) 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 == update @@ -314,11 +321,12 @@ def test_light_client_sync(spec, state): next_slots(spec, state, spec.SLOTS_PER_EPOCH - 1) finalized_block = state_transition_with_full_block(spec, state, True, True) finalized_state = state.copy() - _, _, state = next_slots_with_attestations(spec, state, 2 * spec.SLOTS_PER_EPOCH, True, True) + _, _, state = next_slots_with_attestations(spec, state, 2 * spec.SLOTS_PER_EPOCH - 1, True, True) + attested_block = state_transition_with_full_block(spec, state, True, True) attested_state = state.copy() sync_aggregate, _ = get_sync_aggregate(spec, state) block = state_transition_with_full_block(spec, state, True, True, sync_aggregate=sync_aggregate) - yield from emit_update(test, spec, state, block, attested_state, finalized_block) + yield from emit_update(test, spec, state, block, attested_state, attested_block, finalized_block) assert test.store.finalized_header.slot == finalized_state.slot assert test.store.next_sync_committee == finalized_state.next_sync_committee assert test.store.best_valid_update is None @@ -336,7 +344,8 @@ def test_supply_sync_committee_from_past_update(spec, state): next_slots(spec, state, spec.SLOTS_PER_EPOCH * 2 - 1) finalized_block = state_transition_with_full_block(spec, state, True, True) finalized_state = state.copy() - _, _, state = next_slots_with_attestations(spec, state, 2 * spec.SLOTS_PER_EPOCH, True, True) + _, _, state = next_slots_with_attestations(spec, state, 2 * spec.SLOTS_PER_EPOCH - 1, True, True) + attested_block = state_transition_with_full_block(spec, state, True, True) attested_state = state.copy() sync_aggregate, _ = get_sync_aggregate(spec, state) block = state_transition_with_full_block(spec, state, True, True, sync_aggregate=sync_aggregate) @@ -347,7 +356,7 @@ def test_supply_sync_committee_from_past_update(spec, state): assert not spec.is_next_sync_committee_known(test.store) # Apply `LightClientUpdate` from the past, populating `store.next_sync_committee` - yield from emit_update(test, spec, past_state, block, attested_state, finalized_block) + yield from emit_update(test, spec, past_state, block, attested_state, attested_block, finalized_block) assert test.store.finalized_header.slot == state.slot assert test.store.next_sync_committee == finalized_state.next_sync_committee assert test.store.best_valid_update is None @@ -368,11 +377,12 @@ def test_advance_finality_without_sync_committee(spec, state): next_slots(spec, state, spec.SLOTS_PER_EPOCH - 1) finalized_block = state_transition_with_full_block(spec, state, True, True) finalized_state = state.copy() - _, _, state = next_slots_with_attestations(spec, state, 2 * spec.SLOTS_PER_EPOCH, True, True) + _, _, state = next_slots_with_attestations(spec, state, 2 * spec.SLOTS_PER_EPOCH - 1, True, True) + attested_block = state_transition_with_full_block(spec, state, True, True) attested_state = state.copy() sync_aggregate, _ = get_sync_aggregate(spec, state) block = state_transition_with_full_block(spec, state, True, True, sync_aggregate=sync_aggregate) - yield from emit_update(test, spec, state, block, attested_state, finalized_block) + yield from emit_update(test, spec, state, block, attested_state, attested_block, finalized_block) assert test.store.finalized_header.slot == finalized_state.slot assert test.store.next_sync_committee == finalized_state.next_sync_committee assert test.store.best_valid_update is None @@ -386,11 +396,12 @@ def test_advance_finality_without_sync_committee(spec, state): _, _, state = next_slots_with_attestations(spec, state, spec.SLOTS_PER_EPOCH - 1, True, True) justified_block = state_transition_with_full_block(spec, state, True, True) justified_state = state.copy() - _, _, state = next_slots_with_attestations(spec, state, spec.SLOTS_PER_EPOCH, True, True) + _, _, state = next_slots_with_attestations(spec, state, spec.SLOTS_PER_EPOCH - 1, True, True) + attested_block = state_transition_with_full_block(spec, state, True, True) attested_state = state.copy() sync_aggregate, _ = get_sync_aggregate(spec, state) block = state_transition_with_full_block(spec, state, True, True, sync_aggregate=sync_aggregate) - yield from emit_update(test, spec, state, block, attested_state, finalized_block, with_next_sync_committee=False) + yield from emit_update(test, spec, state, block, attested_state, attested_block, finalized_block, with_next=False) assert test.store.finalized_header.slot == finalized_state.slot assert not spec.is_next_sync_committee_known(test.store) assert test.store.best_valid_update is None @@ -400,27 +411,28 @@ def test_advance_finality_without_sync_committee(spec, state): past_state = finalized_state finalized_block = justified_block finalized_state = justified_state - _, _, state = next_slots_with_attestations(spec, state, spec.SLOTS_PER_EPOCH - 1, True, True) + _, _, state = next_slots_with_attestations(spec, state, spec.SLOTS_PER_EPOCH - 2, True, True) + attested_block = state_transition_with_full_block(spec, state, True, True) attested_state = state.copy() sync_aggregate, _ = get_sync_aggregate(spec, state) block = state_transition_with_full_block(spec, state, True, True, sync_aggregate=sync_aggregate) # Apply `LightClientUpdate` without `finalized_header` nor `next_sync_committee` - update = yield from emit_update(test, spec, state, block, attested_state, None, with_next_sync_committee=False) + update = yield from emit_update(test, spec, state, block, attested_state, attested_block, None, with_next=False) assert test.store.finalized_header.slot == past_state.slot assert not spec.is_next_sync_committee_known(test.store) assert test.store.best_valid_update == update assert test.store.optimistic_header.slot == attested_state.slot # Apply `LightClientUpdate` with `finalized_header` but no `next_sync_committee` - yield from emit_update(test, spec, state, block, attested_state, finalized_block, with_next_sync_committee=False) + yield from emit_update(test, spec, state, block, attested_state, attested_block, finalized_block, with_next=False) assert test.store.finalized_header.slot == finalized_state.slot assert not spec.is_next_sync_committee_known(test.store) assert test.store.best_valid_update is None assert test.store.optimistic_header.slot == attested_state.slot # Apply full `LightClientUpdate`, supplying `next_sync_committee` - yield from emit_update(test, spec, state, block, attested_state, finalized_block) + yield from emit_update(test, spec, state, block, attested_state, attested_block, finalized_block) assert test.store.finalized_header.slot == finalized_state.slot assert test.store.next_sync_committee == finalized_state.next_sync_committee assert test.store.best_valid_update is None diff --git a/tests/core/pyspec/eth2spec/test/altair/light_client/test_update_ranking.py b/tests/core/pyspec/eth2spec/test/altair/light_client/test_update_ranking.py index ae5d5296a..23ad79584 100644 --- a/tests/core/pyspec/eth2spec/test/altair/light_client/test_update_ranking.py +++ b/tests/core/pyspec/eth2spec/test/altair/light_client/test_update_ranking.py @@ -18,13 +18,13 @@ from eth2spec.test.helpers.state import ( from math import floor -def create_update(spec, test, with_next_sync_committee, with_finality, participation_rate): +def create_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_sync_committee: + 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: @@ -84,76 +84,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_sync_committee=1, with_finality=1, participation_rate=1.0), - create_update(spec, lat, with_next_sync_committee=1, with_finality=1, participation_rate=1.0), - create_update(spec, fin, with_next_sync_committee=1, with_finality=1, participation_rate=0.8), - create_update(spec, lat, with_next_sync_committee=1, with_finality=1, participation_rate=0.8), + 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), # Updates without sync committee finality - create_update(spec, att, with_next_sync_committee=1, with_finality=1, participation_rate=1.0), - create_update(spec, att, with_next_sync_committee=1, with_finality=1, participation_rate=0.8), + 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), # Updates without indication of any finality - create_update(spec, att, with_next_sync_committee=1, with_finality=0, participation_rate=1.0), - create_update(spec, fin, with_next_sync_committee=1, with_finality=0, participation_rate=1.0), - create_update(spec, lat, with_next_sync_committee=1, with_finality=0, participation_rate=1.0), - create_update(spec, att, with_next_sync_committee=1, with_finality=0, participation_rate=0.8), - create_update(spec, fin, with_next_sync_committee=1, with_finality=0, participation_rate=0.8), - create_update(spec, lat, with_next_sync_committee=1, with_finality=0, participation_rate=0.8), + 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), # Updates with sync committee finality but no `next_sync_committee` - create_update(spec, sig, with_next_sync_committee=0, with_finality=1, participation_rate=1.0), - create_update(spec, fin, with_next_sync_committee=0, with_finality=1, participation_rate=1.0), - create_update(spec, lat, with_next_sync_committee=0, with_finality=1, participation_rate=1.0), - create_update(spec, sig, with_next_sync_committee=0, with_finality=1, participation_rate=0.8), - create_update(spec, fin, with_next_sync_committee=0, with_finality=1, participation_rate=0.8), - create_update(spec, lat, with_next_sync_committee=0, with_finality=1, participation_rate=0.8), + 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), # Updates without sync committee finality and also no `next_sync_committee` - create_update(spec, att, with_next_sync_committee=0, with_finality=1, participation_rate=1.0), - create_update(spec, att, with_next_sync_committee=0, with_finality=1, participation_rate=0.8), + 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), # Updates without indication of any finality nor `next_sync_committee` - create_update(spec, sig, with_next_sync_committee=0, with_finality=0, participation_rate=1.0), - create_update(spec, att, with_next_sync_committee=0, with_finality=0, participation_rate=1.0), - create_update(spec, fin, with_next_sync_committee=0, with_finality=0, participation_rate=1.0), - create_update(spec, lat, with_next_sync_committee=0, with_finality=0, participation_rate=1.0), - create_update(spec, sig, with_next_sync_committee=0, with_finality=0, participation_rate=0.8), - create_update(spec, att, with_next_sync_committee=0, with_finality=0, participation_rate=0.8), - create_update(spec, fin, with_next_sync_committee=0, with_finality=0, participation_rate=0.8), - create_update(spec, lat, with_next_sync_committee=0, with_finality=0, participation_rate=0.8), + 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), # Updates with low sync committee participation - create_update(spec, fin, with_next_sync_committee=1, with_finality=1, participation_rate=0.4), - create_update(spec, lat, with_next_sync_committee=1, with_finality=1, participation_rate=0.4), - create_update(spec, att, with_next_sync_committee=1, with_finality=1, participation_rate=0.4), - create_update(spec, att, with_next_sync_committee=1, with_finality=0, participation_rate=0.4), - create_update(spec, fin, with_next_sync_committee=1, with_finality=0, participation_rate=0.4), - create_update(spec, lat, with_next_sync_committee=1, with_finality=0, participation_rate=0.4), - create_update(spec, sig, with_next_sync_committee=0, with_finality=1, participation_rate=0.4), - create_update(spec, fin, with_next_sync_committee=0, with_finality=1, participation_rate=0.4), - create_update(spec, lat, with_next_sync_committee=0, with_finality=1, participation_rate=0.4), - create_update(spec, att, with_next_sync_committee=0, with_finality=1, participation_rate=0.4), - create_update(spec, sig, with_next_sync_committee=0, with_finality=0, participation_rate=0.4), - create_update(spec, att, with_next_sync_committee=0, with_finality=0, participation_rate=0.4), - create_update(spec, fin, with_next_sync_committee=0, with_finality=0, participation_rate=0.4), - create_update(spec, lat, with_next_sync_committee=0, with_finality=0, participation_rate=0.4), + 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), # Updates with very low sync committee participation - create_update(spec, fin, with_next_sync_committee=1, with_finality=1, participation_rate=0.2), - create_update(spec, lat, with_next_sync_committee=1, with_finality=1, participation_rate=0.2), - create_update(spec, att, with_next_sync_committee=1, with_finality=1, participation_rate=0.2), - create_update(spec, att, with_next_sync_committee=1, with_finality=0, participation_rate=0.2), - create_update(spec, fin, with_next_sync_committee=1, with_finality=0, participation_rate=0.2), - create_update(spec, lat, with_next_sync_committee=1, with_finality=0, participation_rate=0.2), - create_update(spec, sig, with_next_sync_committee=0, with_finality=1, participation_rate=0.2), - create_update(spec, fin, with_next_sync_committee=0, with_finality=1, participation_rate=0.2), - create_update(spec, lat, with_next_sync_committee=0, with_finality=1, participation_rate=0.2), - create_update(spec, att, with_next_sync_committee=0, with_finality=1, participation_rate=0.2), - create_update(spec, sig, with_next_sync_committee=0, with_finality=0, participation_rate=0.2), - create_update(spec, att, with_next_sync_committee=0, with_finality=0, participation_rate=0.2), - create_update(spec, fin, with_next_sync_committee=0, with_finality=0, participation_rate=0.2), - create_update(spec, lat, with_next_sync_committee=0, with_finality=0, participation_rate=0.2), + 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), ] yield "updates", updates