Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
Expand Up @@ -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)
Expand Down Expand Up @@ -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:
Expand Down
12 changes: 12 additions & 0 deletions packages/testing/src/execution_testing/forks/forks/transition.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
BPO2,
BPO3,
BPO4,
Amsterdam,
Berlin,
Cancun,
London,
Expand Down Expand Up @@ -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."""
Expand Down
33 changes: 23 additions & 10 deletions tests/cancun/eip4844_blobs/test_excess_blob_gas_fork_transition.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand All @@ -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,
)
Expand Down Expand Up @@ -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",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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",
[
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
Loading