|
| 1 | +from eth2spec.test.helpers.block import ( |
| 2 | + build_empty_block_for_next_slot, |
| 3 | +) |
| 4 | +from eth2spec.test.context import ( |
| 5 | + with_presets, |
| 6 | + spec_state_test, |
| 7 | + with_electra_and_later, |
| 8 | +) |
| 9 | +from eth2spec.test.helpers.execution_payload import ( |
| 10 | + compute_el_block_hash_for_block, |
| 11 | +) |
| 12 | +from eth2spec.test.helpers.state import ( |
| 13 | + state_transition_and_sign_block, |
| 14 | + next_slot, |
| 15 | +) |
| 16 | +from eth2spec.test.helpers.deposits import ( |
| 17 | + prepare_deposit_request, |
| 18 | +) |
| 19 | +from eth2spec.test.helpers.fork_choice import ( |
| 20 | + get_genesis_forkchoice_store_and_block, |
| 21 | + tick_and_add_block, |
| 22 | + apply_next_slots_with_attestations, |
| 23 | +) |
| 24 | +from eth2spec.test.helpers.constants import ( |
| 25 | + MINIMAL, |
| 26 | +) |
| 27 | + |
| 28 | + |
| 29 | +@with_electra_and_later |
| 30 | +@spec_state_test |
| 31 | +@with_presets([MINIMAL], reason="too slow") |
| 32 | +def test_new_validator_deposit_with_multiple_epoch_transitions(spec, state): |
| 33 | + # signify the eth1 bridge deprecation |
| 34 | + state.deposit_requests_start_index = state.eth1_deposit_index |
| 35 | + |
| 36 | + # yield anchor state and block |
| 37 | + store, anchor_block = get_genesis_forkchoice_store_and_block(spec, state) |
| 38 | + yield 'anchor_state', state |
| 39 | + yield 'anchor_block', anchor_block |
| 40 | + |
| 41 | + test_steps = [] |
| 42 | + |
| 43 | + # (1) create deposit request for a new validator |
| 44 | + deposit_request = prepare_deposit_request( |
| 45 | + spec, len(state.validators), spec.MIN_ACTIVATION_BALANCE, signed=True) |
| 46 | + deposit_block = build_empty_block_for_next_slot(spec, state) |
| 47 | + deposit_block.body.execution_requests.deposits = [deposit_request] |
| 48 | + deposit_block.body.execution_payload.block_hash = compute_el_block_hash_for_block(spec, deposit_block) |
| 49 | + signed_deposit_block = state_transition_and_sign_block(spec, state, deposit_block) |
| 50 | + |
| 51 | + pending_deposit = spec.PendingDeposit( |
| 52 | + pubkey=deposit_request.pubkey, |
| 53 | + withdrawal_credentials=deposit_request.withdrawal_credentials, |
| 54 | + amount=deposit_request.amount, |
| 55 | + signature=deposit_request.signature, |
| 56 | + slot=deposit_block.slot |
| 57 | + ) |
| 58 | + |
| 59 | + assert state.pending_deposits == [pending_deposit] |
| 60 | + |
| 61 | + yield from tick_and_add_block(spec, store, signed_deposit_block, test_steps) |
| 62 | + |
| 63 | + # (2) finalize and process pending deposit on one fork |
| 64 | + slots = 4 * spec.SLOTS_PER_EPOCH - state.slot |
| 65 | + post_state, _, latest_block = yield from apply_next_slots_with_attestations( |
| 66 | + spec, state, store, slots, True, True, test_steps) |
| 67 | + |
| 68 | + # check new validator has been created |
| 69 | + assert post_state.pending_deposits == [] |
| 70 | + new_validator = post_state.validators[len(post_state.validators) - 1] |
| 71 | + assert new_validator.pubkey == pending_deposit.pubkey |
| 72 | + assert new_validator.withdrawal_credentials == pending_deposit.withdrawal_credentials |
| 73 | + |
| 74 | + # (3) create a conflicting block that triggers deposit processing on another fork |
| 75 | + prev_epoch_ancestor = store.blocks[latest_block.message.parent_root] |
| 76 | + # important to skip last block of the epoch to make client do the epoch processing |
| 77 | + # otherwise, client can read the post-epoch from cache |
| 78 | + prev_epoch_ancestor = store.blocks[prev_epoch_ancestor.parent_root] |
| 79 | + another_fork_state = store.block_states[prev_epoch_ancestor.hash_tree_root()].copy() |
| 80 | + |
| 81 | + assert another_fork_state.pending_deposits == [pending_deposit] |
| 82 | + |
| 83 | + # skip a slot to create and process a fork block |
| 84 | + next_slot(spec, another_fork_state) |
| 85 | + post_state, _, _ = yield from apply_next_slots_with_attestations( |
| 86 | + spec, another_fork_state, store, 1, True, True, test_steps) |
| 87 | + |
| 88 | + # check new validator has been created on another fork |
| 89 | + assert post_state.pending_deposits == [] |
| 90 | + new_validator = post_state.validators[len(post_state.validators) - 1] |
| 91 | + assert new_validator.pubkey == pending_deposit.pubkey |
| 92 | + assert new_validator.withdrawal_credentials == pending_deposit.withdrawal_credentials |
| 93 | + |
| 94 | + yield 'steps', test_steps |
0 commit comments