Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add test verifying validator creation on two forks #4112

Merged
merged 7 commits into from
Feb 1, 2025
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from eth2spec.test.helpers.block import (
build_empty_block_for_next_slot
build_empty_block_for_next_slot,
apply_empty_block,
sign_block,
)
from eth2spec.test.context import (
spec_state_test,
Expand All @@ -16,11 +18,19 @@
)
from eth2spec.test.helpers.state import (
state_transition_and_sign_block,
next_epoch_with_full_participation,
next_epoch_via_signed_block,
set_full_participation,
next_epoch,
)
from eth2spec.test.helpers.withdrawals import (
set_eth1_withdrawal_credential_with_balance,
set_compounding_withdrawal_credential_with_balance,
)
from eth2spec.test.helpers.deposits import (
prepare_deposit_request,
prepare_pending_deposit,
)


@with_electra_and_later
Expand Down Expand Up @@ -327,3 +337,91 @@ def test_withdrawal_and_switch_to_compounding_request_same_validator(spec, state
assert spec.is_compounding_withdrawal_credential(state.validators[validator_index].withdrawal_credentials)
# Ensure there was no excess balance pending deposit
assert len(state.pending_deposits) == 0


@with_electra_and_later
@spec_state_test
def test_deposit_request_with_same_pubkey_different_withdrawal_credentials(spec, state):
# signify the eth1 bridge deprecation
state.deposit_requests_start_index = state.eth1_deposit_index

# prepare three deposit requests, where
# 1st and 3rd have the same pubkey but different withdrawal credentials
deposit_request_0 = prepare_deposit_request(
spec, len(state.validators), spec.MIN_ACTIVATION_BALANCE, state.eth1_deposit_index, signed=True)
deposit_request_1 = prepare_deposit_request(
spec, len(state.validators) + 1, spec.MIN_ACTIVATION_BALANCE, state.eth1_deposit_index + 1, signed=True)
deposit_request_2 = prepare_deposit_request(
spec, len(state.validators), spec.MIN_ACTIVATION_BALANCE, state.eth1_deposit_index + 2, signed=True,
withdrawal_credentials=(spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX + b'\x00' * 11 + b'\x11' * 20)
)

# build a block with deposit requests
block = build_empty_block_for_next_slot(spec, state)
block.body.execution_requests.deposits = [deposit_request_0, deposit_request_1, deposit_request_2]
block.body.execution_payload.block_hash = compute_el_block_hash_for_block(spec, block)

yield 'pre', state

signed_block = state_transition_and_sign_block(spec, state, block)

yield 'blocks', [signed_block]
yield 'post', state

# check deposit requests are processed correctly
for i, deposit_request in enumerate(block.body.execution_requests.deposits):
assert state.pending_deposits[i] == spec.PendingDeposit(
pubkey=deposit_request.pubkey,
withdrawal_credentials=deposit_request.withdrawal_credentials,
amount=deposit_request.amount,
signature=deposit_request.signature,
slot=signed_block.message.slot,
)


@with_electra_and_later
@spec_state_test
def test_new_validator_deposit_with_multiple_epoch_transitions(spec, state):
# signify the eth1 bridge deprecation
state.deposit_requests_start_index = state.eth1_deposit_index

# (1) create pending deposit for a new validator and finalize it
pending_deposit = prepare_pending_deposit(
spec, len(state.validators), spec.MIN_ACTIVATION_BALANCE, signed=True, slot=spec.Slot(1))
state.pending_deposits.append(pending_deposit)

# do required state transitions and fill participation to get Slot(1) finalized
next_epoch_with_full_participation(spec, state)
next_epoch_with_full_participation(spec, state)
next_epoch_with_full_participation(spec, state)
set_full_participation(spec, state)

# pending deposit is not yet processed
assert state.pending_deposits == [pending_deposit]

yield 'pre', state

# (2) create and apply a block for the next epoch so the new validator gets created
block_a_state = state.copy()
signed_block_a = next_epoch_via_signed_block(spec, block_a_state)

# check that the validator has been created
assert block_a_state.pending_deposits == []
new_validator = block_a_state.validators[len(block_a_state.validators) - 1]
assert new_validator.pubkey == pending_deposit.pubkey
assert new_validator.withdrawal_credentials == pending_deposit.withdrawal_credentials

# (3) create and apply a block conflicting with "block_a"
# so the epoch processing will be triggered once again
# and the validator will be created on another branch of the block tree
next_epoch(spec, state)
block_b = apply_empty_block(spec, state, state.slot + 1)
signed_block_b = sign_block(spec, state, block_b)

# check that the validator has been created in the "block_b" fork
new_validator = state.validators[len(state.validators) - 1]
assert new_validator.pubkey == pending_deposit.pubkey
assert new_validator.withdrawal_credentials == pending_deposit.withdrawal_credentials

yield 'blocks', [signed_block_a, signed_block_b]
yield 'post', state
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,8 @@ def prepare_state_and_block(spec,
deposit_data = build_deposit_data(spec,
pubkeys[keypair_index],
privkeys[keypair_index],
# use max effective balance
spec.MAX_EFFECTIVE_BALANCE,
# use min activation balance
spec.MIN_ACTIVATION_BALANCE,
# insecurely use pubkey as withdrawal key
spec.BLS_WITHDRAWAL_PREFIX + spec.hash(pubkeys[keypair_index])[1:],
signed=True)
Expand All @@ -118,8 +118,8 @@ def prepare_state_and_block(spec,
for offset in range(deposit_request_cnt):
deposit_request = prepare_deposit_request(spec,
keypair_index,
# use max effective balance
spec.MAX_EFFECTIVE_BALANCE,
# use min activation balance
spec.MIN_ACTIVATION_BALANCE,
first_deposit_request_index + offset,
signed=True)
deposit_requests.append(deposit_request)
Expand Down
Loading