diff --git a/packages/testing/src/execution_testing/cli/pytest_commands/plugins/forks/forks.py b/packages/testing/src/execution_testing/cli/pytest_commands/plugins/forks/forks.py index 197e9f595d..5c089f1570 100644 --- a/packages/testing/src/execution_testing/cli/pytest_commands/plugins/forks/forks.py +++ b/packages/testing/src/execution_testing/cli/pytest_commands/plugins/forks/forks.py @@ -1181,6 +1181,24 @@ def add_fork_covariant_parameters( fp for fp in fork_parametrizers if fp.fork >= param_min_fork ] + # Filter out forks where blob params don't change for valid_for_bpo_forks + if list(metafunc.definition.iter_markers(name="valid_for_bpo_forks")): + filtered_forks = [ + fp.fork + for fp in fork_parametrizers + if not blob_params_changed_at_transition(fp.fork) + ] + if filtered_forks: + logger.debug( + f"Skipping {metafunc.function.__name__} for forks with " + f"unchanged blob params: {[f.name() for f in filtered_forks]}" + ) + fork_parametrizers[:] = [ + fp + for fp in fork_parametrizers + if blob_params_changed_at_transition(fp.fork) + ] + for covariant_descriptor in fork_covariant_decorators: if list( metafunc.definition.iter_markers(covariant_descriptor.marker_name) @@ -1272,6 +1290,48 @@ def parametrize_fork( ) +def blob_params_changed_at_transition(fork: Fork) -> bool: + """ + Check if BPO-relevant blob parameters change at a fork transition. + + For transition forks, compares the 3 blob parameters that BPO forks modify + between the from_fork and to_fork: + + - target_blobs_per_block + - max_blobs_per_block + - blob_base_fee_update_fraction + + Returns True if any parameter changed, False otherwise. + + For non-transition forks, returns True (no filtering needed). + """ + # Check if this is a transition fork + if not hasattr(fork, "transitions_from") or not hasattr( + fork, "transitions_to" + ): + return True + + from_fork = fork.transitions_from() + to_fork = fork.transitions_to() + + # Compare the 3 blob parameters that BPO forks modify + bpo_blob_params = [ + "target_blobs_per_block", + "max_blobs_per_block", + "blob_base_fee_update_fraction", + ] + + for param in bpo_blob_params: + from_method = getattr(from_fork, param, None) + to_method = getattr(to_fork, param, None) + if from_method is None or to_method is None: + continue + if from_method() != to_method(): + return True + + return False + + def pytest_collection_modifyitems( config: pytest.Config, items: List[pytest.Item] ) -> None: diff --git a/packages/testing/src/execution_testing/forks/forks/transition.py b/packages/testing/src/execution_testing/forks/forks/transition.py index 249314098e..85c43a2c4d 100644 --- a/packages/testing/src/execution_testing/forks/forks/transition.py +++ b/packages/testing/src/execution_testing/forks/forks/transition.py @@ -6,6 +6,7 @@ BPO2, BPO3, BPO4, + Amsterdam, Berlin, Cancun, London, @@ -66,6 +67,17 @@ class BPO1ToBPO2AtTime15k(BPO1): pass +@transition_fork(to_fork=Amsterdam, at_timestamp=15_000) +class BPO2ToAmsterdamAtTime15k(BPO2): + """BPO2 to Amsterdam transition at Timestamp 15k.""" + + # TODO: We may need to adjust which BPO Amsterdam inherits from as the + # related Amsterdam specs change over time, and before Amsterdam is + # live on mainnet. + + pass + + @transition_fork(to_fork=BPO3, at_timestamp=15_000) class BPO2ToBPO3AtTime15k(BPO2): """BPO2 to BPO3 transition at Timestamp 15k.""" diff --git a/tests/cancun/eip4844_blobs/test_excess_blob_gas_fork_transition.py b/tests/cancun/eip4844_blobs/test_excess_blob_gas_fork_transition.py index d88207cfce..1866a4e210 100644 --- a/tests/cancun/eip4844_blobs/test_excess_blob_gas_fork_transition.py +++ b/tests/cancun/eip4844_blobs/test_excess_blob_gas_fork_transition.py @@ -158,24 +158,36 @@ def pre_fork_blocks( @pytest.fixture -def pre_fork_excess_blobs( +def pre_fork_excess_blob_gas( fork: Fork, pre_fork_blobs_per_block: int, pre_fork_blocks: List[Block], + block_base_fee_per_gas: int, ) -> int: """ - Return the cumulative excess blobs up until the fork given the - pre_fork_blobs_per_block and the target blobs in the fork prior. + Return the cumulative excess blob gas up until the fork. + + Calculates the expected excess blob gas by iterating through pre-fork + blocks using the fork's calculator, which handles EIP-7918 reserve price + for >=Osaka. """ if not fork.supports_blobs(timestamp=0): return 0 - target_blobs = fork.target_blobs_per_block(timestamp=0) - if pre_fork_blobs_per_block > target_blobs: - return (pre_fork_blobs_per_block - target_blobs) * ( - len(pre_fork_blocks) - 1 + calc_excess_blob_gas = fork.excess_blob_gas_calculator(timestamp=0) + excess_blob_gas = 0 + + # Calculate excess accumulation for each pre-fork block + # First block is built on genesis which has 0 blobs + for i in range(len(pre_fork_blocks)): + parent_blob_count = 0 if i == 0 else pre_fork_blobs_per_block + excess_blob_gas = calc_excess_blob_gas( + parent_excess_blob_gas=excess_blob_gas, + parent_blob_count=parent_blob_count, + parent_base_fee_per_gas=block_base_fee_per_gas, ) - return 0 + + return excess_blob_gas @pytest.fixture @@ -204,7 +216,7 @@ def gas_spender_account(pre: Alloc) -> Address: # noqa: D103 @pytest.fixture def fork_block_excess_blob_gas( fork: Fork, - pre_fork_excess_blobs: int, + pre_fork_excess_blob_gas: int, pre_fork_blobs_per_block: int, block_base_fee_per_gas: int, ) -> int: @@ -215,7 +227,7 @@ def fork_block_excess_blob_gas( timestamp=FORK_TIMESTAMP ) return calc_excess_blob_gas_post_fork( - parent_excess_blobs=pre_fork_excess_blobs, + parent_excess_blob_gas=pre_fork_excess_blob_gas, parent_blob_count=pre_fork_blobs_per_block, parent_base_fee_per_gas=block_base_fee_per_gas, ) @@ -463,6 +475,7 @@ def test_fork_transition_excess_blob_gas_at_blob_genesis( ) +@pytest.mark.valid_for_bpo_forks @pytest.mark.valid_at_transition_to("Prague", subsequent_forks=True) @pytest.mark.parametrize_by_fork( "post_fork_block_count,pre_fork_blobs_per_block,post_fork_blobs_per_block", diff --git a/tests/osaka/eip7823_modexp_upper_bounds/test_modexp_upper_bounds.py b/tests/osaka/eip7823_modexp_upper_bounds/test_modexp_upper_bounds.py index 60ae982971..264219cd36 100644 --- a/tests/osaka/eip7823_modexp_upper_bounds/test_modexp_upper_bounds.py +++ b/tests/osaka/eip7823_modexp_upper_bounds/test_modexp_upper_bounds.py @@ -283,7 +283,7 @@ def test_modexp_upper_bounds( ), ], ) -@pytest.mark.valid_at_transition_to("Osaka", subsequent_forks=True) +@pytest.mark.valid_at_transition_to("Osaka") def test_modexp_upper_bounds_fork_transition( blockchain_test: BlockchainTestFiller, pre: Alloc, diff --git a/tests/osaka/eip7825_transaction_gas_limit_cap/test_tx_gas_limit_transition_fork.py b/tests/osaka/eip7825_transaction_gas_limit_cap/test_tx_gas_limit_transition_fork.py index fc952760b3..243ce4640e 100644 --- a/tests/osaka/eip7825_transaction_gas_limit_cap/test_tx_gas_limit_transition_fork.py +++ b/tests/osaka/eip7825_transaction_gas_limit_cap/test_tx_gas_limit_transition_fork.py @@ -28,7 +28,7 @@ @EIPChecklist.ModifiedTransactionValidityConstraint.Test.ForkTransition.RejectedBeforeFork() @EIPChecklist.ModifiedTransactionValidityConstraint.Test.ForkTransition.AcceptedAfterFork() @EIPChecklist.ModifiedTransactionValidityConstraint.Test.ForkTransition.RejectedAfterFork() -@pytest.mark.valid_at_transition_to("Osaka", subsequent_forks=True) +@pytest.mark.valid_at_transition_to("Osaka") @pytest.mark.parametrize( "transaction_at_cap", [ diff --git a/tests/osaka/eip7883_modexp_gas_increase/test_modexp_thresholds_transition.py b/tests/osaka/eip7883_modexp_gas_increase/test_modexp_thresholds_transition.py index be711225a2..128d1306a7 100644 --- a/tests/osaka/eip7883_modexp_gas_increase/test_modexp_thresholds_transition.py +++ b/tests/osaka/eip7883_modexp_gas_increase/test_modexp_thresholds_transition.py @@ -21,7 +21,7 @@ REFERENCE_SPEC_GIT_PATH = ref_spec_7883.git_path REFERENCE_SPEC_VERSION = ref_spec_7883.version -pytestmark = pytest.mark.valid_at_transition_to("Osaka", subsequent_forks=True) +pytestmark = pytest.mark.valid_at_transition_to("Osaka") @pytest.mark.parametrize( diff --git a/tests/osaka/eip7939_count_leading_zeros/test_count_leading_zeros.py b/tests/osaka/eip7939_count_leading_zeros/test_count_leading_zeros.py index ec4e7ac17f..746e1794c3 100644 --- a/tests/osaka/eip7939_count_leading_zeros/test_count_leading_zeros.py +++ b/tests/osaka/eip7939_count_leading_zeros/test_count_leading_zeros.py @@ -284,7 +284,7 @@ def test_clz_push_operation_same_value( @EIPChecklist.Opcode.Test.ForkTransition.Invalid() @EIPChecklist.Opcode.Test.ForkTransition.At() -@pytest.mark.valid_at_transition_to("Osaka", subsequent_forks=True) +@pytest.mark.valid_at_transition_to("Osaka") def test_clz_fork_transition( blockchain_test: BlockchainTestFiller, pre: Alloc ) -> None: