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 3997a2d09..501269ee2 100644 --- a/specs/altair/light-client/p2p-interface.md +++ b/specs/altair/light-client/p2p-interface.md @@ -138,7 +138,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