diff --git a/tests/core/pyspec/eth2spec/test/eip4844/block_processing/__init__.py b/tests/core/pyspec/eth2spec/test/eip4844/block_processing/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/core/pyspec/eth2spec/test/eip4844/block_processing/test_process_bls_to_execution_change.py b/tests/core/pyspec/eth2spec/test/eip4844/block_processing/test_process_bls_to_execution_change.py new file mode 100644 index 000000000..d9b93394f --- /dev/null +++ b/tests/core/pyspec/eth2spec/test/eip4844/block_processing/test_process_bls_to_execution_change.py @@ -0,0 +1,40 @@ +from eth2spec.test.helpers.bls_to_execution_changes import get_signed_address_change +from eth2spec.test.context import spec_state_test, expect_assertion_error, with_eip4844_and_later + + +def run_bls_to_execution_change_processing_no_op(spec, state, signed_address_change, valid=True): + """ + Run ``process_bls_to_execution_change``, yielding: + - pre-state ('pre') + - address-change ('address_change') + - post-state ('post'). + If ``valid == False``, run expecting ``AssertionError`` + """ + pre_state = state.copy() + + # yield pre-state + yield 'pre', state + + yield 'address_change', signed_address_change + + # If the address_change is invalid, processing is aborted, and there is no post-state. + if not valid: + expect_assertion_error(lambda: spec.process_bls_to_execution_change(state, signed_address_change)) + yield 'post', None + return + + # process address change + spec.process_bls_to_execution_change(state, signed_address_change) + + # yield post-state + yield 'post', state + + # Make sure state has NOT been changed + assert state == pre_state + + +@with_eip4844_and_later +@spec_state_test +def test_no_op(spec, state): + signed_address_change = get_signed_address_change(spec, state) + yield from run_bls_to_execution_change_processing_no_op(spec, state, signed_address_change) diff --git a/tests/core/pyspec/eth2spec/test/eip4844/epoch_processing/__init__.py b/tests/core/pyspec/eth2spec/test/eip4844/epoch_processing/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/core/pyspec/eth2spec/test/eip4844/epoch_processing/test_process_full_withdrawals.py b/tests/core/pyspec/eth2spec/test/eip4844/epoch_processing/test_process_full_withdrawals.py new file mode 100644 index 000000000..1a7cda91d --- /dev/null +++ b/tests/core/pyspec/eth2spec/test/eip4844/epoch_processing/test_process_full_withdrawals.py @@ -0,0 +1,43 @@ +from eth2spec.test.context import ( + with_eip4844_and_later, + spec_state_test, +) +from eth2spec.test.helpers.epoch_processing import ( + run_epoch_processing_to, +) +from eth2spec.test.helpers.withdrawals import ( + set_validator_fully_withdrawable, +) + + +def run_process_full_withdrawals_no_op(spec, state, num_expected_withdrawals=None): + run_epoch_processing_to(spec, state, 'process_full_withdrawals') + + state.next_withdrawal_index = 0 + to_be_withdrawn_indices = [ + index for index, validator in enumerate(state.validators) + if spec.is_fully_withdrawable_validator(validator, state.balances[index], spec.get_current_epoch(state)) + ] + + if num_expected_withdrawals is not None: + assert len(to_be_withdrawn_indices) == num_expected_withdrawals + else: + num_expected_withdrawals = len(to_be_withdrawn_indices) + + pre_state = state.copy() + + yield 'pre', state + spec.process_full_withdrawals(state) + yield 'post', state + + # Make sure state has NOT been changed + assert state == pre_state + + +@with_eip4844_and_later +@spec_state_test +def test_no_op(spec, state): + # Make one validator withdrawable + set_validator_fully_withdrawable(spec, state, 0) + + yield from run_process_full_withdrawals_no_op(spec, state, 1) diff --git a/tests/core/pyspec/eth2spec/test/eip4844/epoch_processing/test_process_partial_withdrawals.py b/tests/core/pyspec/eth2spec/test/eip4844/epoch_processing/test_process_partial_withdrawals.py new file mode 100644 index 000000000..992133420 --- /dev/null +++ b/tests/core/pyspec/eth2spec/test/eip4844/epoch_processing/test_process_partial_withdrawals.py @@ -0,0 +1,43 @@ +from eth2spec.test.context import ( + spec_state_test, + with_eip4844_and_later, +) +from eth2spec.test.helpers.epoch_processing import run_epoch_processing_to +from eth2spec.test.helpers.withdrawals import ( + set_validator_partially_withdrawable, +) + + +def run_process_partial_withdrawals_no_op(spec, state, num_expected_withdrawals=None): + # Run rest of epoch processing before predicting partial withdrawals as + # balance changes can affect withdrawability + run_epoch_processing_to(spec, state, 'process_partial_withdrawals') + + partially_withdrawable_indices = [ + index for index, validator in enumerate(state.validators) + if spec.is_partially_withdrawable_validator(validator, state.balances[index]) + ] + num_partial_withdrawals = min(len(partially_withdrawable_indices), spec.MAX_PARTIAL_WITHDRAWALS_PER_EPOCH) + + if num_expected_withdrawals is not None: + assert num_partial_withdrawals == num_expected_withdrawals + else: + num_expected_withdrawals = num_partial_withdrawals + + pre_state = state.copy() + + yield 'pre', state + spec.process_partial_withdrawals(state) + yield 'post', state + + # Make sure state has NOT been changed + assert state == pre_state + + +@with_eip4844_and_later +@spec_state_test +def test_success_one_partial_withdrawable(spec, state): + validator_index = len(state.validators) // 2 + set_validator_partially_withdrawable(spec, state, validator_index) + + yield from run_process_partial_withdrawals_no_op(spec, state, 1)