Skip to content

Commit

Permalink
Changes to Fork library (#28)
Browse files Browse the repository at this point in the history
Co-authored-by: danceratopz <danceratopz@gmail.com>
  • Loading branch information
marioevz and danceratopz authored Jan 31, 2024
1 parent 8c8bc14 commit 4ab1a93
Show file tree
Hide file tree
Showing 10 changed files with 73 additions and 86 deletions.
3 changes: 1 addition & 2 deletions src/ethereum_test_forks/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Ethereum test fork definitions.
"""

from .base_fork import SOLC_VERSION_TO_SUPPORTED_FORKS, Fork, ForkAttribute
from .base_fork import Fork, ForkAttribute
from .forks.forks import (
ArrowGlacier,
Berlin,
Expand Down Expand Up @@ -40,7 +40,6 @@
)

__all__ = [
"SOLC_VERSION_TO_SUPPORTED_FORKS",
"Fork",
"ForkAttribute",
"ArrowGlacier",
Expand Down
32 changes: 4 additions & 28 deletions src/ethereum_test_forks/base_fork.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,6 @@

from .base_decorators import prefer_transition_to_method

SOLC_FORKS_0_8_20 = [
"homestead",
"tangerineWhistle",
"spuriousDragon",
"byzantium",
"constantinople",
"petersburg",
"istanbul",
"berlin",
"london",
"paris",
"shanghai",
]
SOLC_VERSION_TO_SUPPORTED_FORKS = {
Version.parse("0.8.20"): SOLC_FORKS_0_8_20,
Version.parse("0.8.21"): SOLC_FORKS_0_8_20,
Version.parse("0.8.22"): SOLC_FORKS_0_8_20,
Version.parse("0.8.23"): SOLC_FORKS_0_8_20,
# TBA: 0.8.24 is the current dev version.
Version.parse("0.8.24"): SOLC_FORKS_0_8_20,
}


class ForkAttribute(Protocol):
"""
Expand Down Expand Up @@ -283,14 +261,12 @@ def solc_name(cls, block_number: int = 0, timestamp: int = 0) -> str:
pass

@classmethod
def is_supported_by_solc(cls, version: Version) -> bool:
@abstractmethod
def solc_min_version(cls, block_number: int = 0, timestamp: int = 0) -> Version:
"""
Returns True if the fork is supported by solc (--evm-version).
Returns the minimum version of solc that supports this fork.
"""
assert (
version in SOLC_VERSION_TO_SUPPORTED_FORKS.keys()
), f"Unsupported solc version: {version}"
return cls.solc_name() in SOLC_VERSION_TO_SUPPORTED_FORKS[version]
pass

@classmethod
def blockchain_test_network_name(cls) -> str:
Expand Down
43 changes: 29 additions & 14 deletions src/ethereum_test_forks/forks/forks.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
"""
from typing import List, Mapping, Optional

from semver import Version

from ..base_fork import BaseFork


# All forks must be listed here !!! in the order they were introduced !!!
class Frontier(BaseFork, solc_name=None):
class Frontier(BaseFork, solc_name="homestead"):
"""
Frontier fork
"""
Expand All @@ -28,7 +30,14 @@ def solc_name(cls, block_number: int = 0, timestamp: int = 0) -> str:
"""
if cls._solc_name is not None:
return cls._solc_name
return cls.name()
return cls.name().lower()

@classmethod
def solc_min_version(cls, block_number: int = 0, timestamp: int = 0) -> Version:
"""
Returns the minimum version of solc that supports this fork.
"""
return Version.parse("0.8.20")

@classmethod
def header_base_fee_required(cls, block_number: int = 0, timestamp: int = 0) -> bool:
Expand Down Expand Up @@ -150,7 +159,7 @@ def pre_allocation(cls, block_number: int = 0, timestamp: int = 0) -> Mapping:
return {}


class Homestead(Frontier, solc_name="homestead"):
class Homestead(Frontier):
"""
Homestead fork
"""
Expand All @@ -163,7 +172,7 @@ def precompiles(cls, block_number: int = 0, timestamp: int = 0) -> List[int]:
return [1, 2, 3, 4] + super(Homestead, cls).precompiles(block_number, timestamp)


class Byzantium(Homestead, solc_name="byzantium"):
class Byzantium(Homestead):
"""
Byzantium fork
"""
Expand All @@ -186,7 +195,7 @@ def precompiles(cls, block_number: int = 0, timestamp: int = 0) -> List[int]:
return [5, 6, 7, 8] + super(Byzantium, cls).precompiles(block_number, timestamp)


class Constantinople(Byzantium, solc_name="constantinople"):
class Constantinople(Byzantium):
"""
Constantinople fork
"""
Expand All @@ -208,7 +217,7 @@ class ConstantinopleFix(Constantinople, solc_name="constantinople"):
pass


class Istanbul(ConstantinopleFix, solc_name="istanbul"):
class Istanbul(ConstantinopleFix):
"""
Istanbul fork
"""
Expand All @@ -222,15 +231,15 @@ def precompiles(cls, block_number: int = 0, timestamp: int = 0) -> List[int]:


# Glacier forks skipped, unless explicitly specified
class MuirGlacier(Istanbul):
class MuirGlacier(Istanbul, solc_name="istanbul"):
"""
Muir Glacier fork
"""

pass


class Berlin(Istanbul, solc_name="berlin"):
class Berlin(Istanbul):
"""
Berlin fork
"""
Expand All @@ -243,7 +252,7 @@ def tx_types(cls, block_number: int = 0, timestamp: int = 0) -> List[int]:
return [1] + super(Berlin, cls).tx_types(block_number, timestamp)


class London(Berlin, solc_name="london"):
class London(Berlin):
"""
London fork
"""
Expand All @@ -264,15 +273,15 @@ def tx_types(cls, block_number: int = 0, timestamp: int = 0) -> List[int]:


# Glacier forks skipped, unless explicitly specified
class ArrowGlacier(London):
class ArrowGlacier(London, solc_name="london"):
"""
Arrow Glacier fork
"""

pass


class GrayGlacier(ArrowGlacier):
class GrayGlacier(ArrowGlacier, solc_name="london"):
"""
Gray Glacier fork
"""
Expand All @@ -282,7 +291,6 @@ class GrayGlacier(ArrowGlacier):

class Paris(
London,
solc_name="paris",
transition_tool_name="Merge",
blockchain_test_network_name="Merge",
):
Expand Down Expand Up @@ -321,7 +329,7 @@ def engine_new_payload_version(
return 1


class Shanghai(Paris, solc_name="shanghai"):
class Shanghai(Paris):
"""
Shanghai fork
"""
Expand All @@ -343,7 +351,7 @@ def engine_new_payload_version(
return 2


class Cancun(Shanghai, solc_name="cancun"):
class Cancun(Shanghai):
"""
Cancun fork
"""
Expand All @@ -356,6 +364,13 @@ def is_deployed(cls):
"""
return False

@classmethod
def solc_min_version(cls, block_number: int = 0, timestamp: int = 0) -> Version:
"""
Returns the minimum version of solc that supports this fork.
"""
return Version.parse("0.8.24")

@classmethod
def header_excess_blob_gas_required(cls, block_number: int = 0, timestamp: int = 0) -> bool:
"""
Expand Down
24 changes: 11 additions & 13 deletions src/ethereum_test_forks/helpers.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
"""
Helper methods to resolve forks during test filling
"""
from typing import List
from typing import List, Optional

from semver import Version

from .base_fork import BaseFork, Fork
from .forks import forks, transition
from .forks.forks import Frontier, Homestead
from .transition_base_fork import TransitionBaseClass


Expand Down Expand Up @@ -64,29 +63,28 @@ def get_forks_with_solc_support(solc_version: Version) -> List[Fork]:
"""
Returns a list of all fork classes that are supported by solc.
"""
return [fork for fork in get_forks() if fork.is_supported_by_solc(solc_version)]
return [fork for fork in get_forks() if solc_version >= fork.solc_min_version()]


def get_forks_without_solc_support(solc_version: Version) -> List[Fork]:
"""
Returns a list of all fork classes that aren't supported by solc.
"""
return [fork for fork in get_forks() if not fork.is_supported_by_solc(solc_version)]
return [fork for fork in get_forks() if solc_version < fork.solc_min_version()]


def get_closest_fork_with_solc_support(fork: Fork, solc_version: Version) -> Fork:
def get_closest_fork_with_solc_support(fork: Fork, solc_version: Version) -> Optional[Fork]:
"""
Returns the closest fork, potentially the provided fork itself, that has
solc support.
"""
if fork == Frontier:
return Homestead
if fork in get_forks_with_solc_support(solc_version):
return fork
parent_fork = get_parent_fork(fork)
if parent_fork.is_supported_by_solc(solc_version):
return parent_fork
return get_closest_fork_with_solc_support(parent_fork, solc_version)
if fork is BaseFork:
return None
return (
fork
if solc_version >= fork.solc_min_version()
else get_closest_fork_with_solc_support(get_parent_fork(fork), solc_version)
)


def get_transition_forks() -> List[Fork]:
Expand Down
15 changes: 15 additions & 0 deletions src/ethereum_test_forks/tests/test_forks.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,19 @@

from typing import Mapping, cast

from semver import Version

from ..base_fork import Fork
from ..forks.forks import Berlin, Cancun, Frontier, London, Paris, Shanghai
from ..forks.transition import BerlinToLondonAt5, ParisToShanghaiAtTime15k
from ..helpers import (
forks_from,
forks_from_until,
get_closest_fork_with_solc_support,
get_deployed_forks,
get_development_forks,
get_forks,
get_forks_with_solc_support,
transition_fork_from_to,
transition_fork_to,
)
Expand Down Expand Up @@ -214,3 +218,14 @@ def test_precompiles():

def test_tx_types():
Cancun.tx_types() == list(range(4))


def test_solc_versioning():
assert len(get_forks_with_solc_support(Version.parse("0.8.20"))) == 13
assert len(get_forks_with_solc_support(Version.parse("0.8.24"))) > 13


def test_closest_fork_supported_by_solc():
assert get_closest_fork_with_solc_support(Paris, Version.parse("0.8.20")) == Paris
assert get_closest_fork_with_solc_support(Cancun, Version.parse("0.8.20")) == Shanghai
assert get_closest_fork_with_solc_support(Cancun, Version.parse("0.8.24")) == Cancun
3 changes: 1 addition & 2 deletions src/ethereum_test_tools/code/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@
"""
from .code import Code
from .generators import CalldataCase, Case, CodeGasMeasure, Conditional, Initcode, Switch
from .yul import SOLC_SUPPORTED_VERSIONS, Yul, YulCompiler
from .yul import Yul, YulCompiler

__all__ = (
"SOLC_SUPPORTED_VERSIONS",
"Case",
"CalldataCase",
"Code",
Expand Down
4 changes: 1 addition & 3 deletions src/ethereum_test_tools/code/yul.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,13 @@

from semver import Version

from ethereum_test_forks import SOLC_VERSION_TO_SUPPORTED_FORKS, Fork
from ethereum_test_forks import Fork

from ..common.conversions import to_bytes
from .code import Code

DEFAULT_SOLC_ARGS = ("--assemble", "-")

SOLC_SUPPORTED_VERSIONS = list(SOLC_VERSION_TO_SUPPORTED_FORKS.keys())


def get_evm_version_from_fork(fork: Fork | None):
"""
Expand Down
6 changes: 4 additions & 2 deletions src/ethereum_test_tools/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
import pytest
from semver import Version

from ..code import SOLC_SUPPORTED_VERSIONS, Yul
from ethereum_test_forks import Frontier

from ..code import Yul

SOLC_PADDING_VERSION = Version.parse("0.8.21")

Expand All @@ -14,6 +16,6 @@
def solc_version() -> Version:
"""Return the version of solc being used for tests."""
solc_version = Yul("").version().finalize_version()
if solc_version not in SOLC_SUPPORTED_VERSIONS:
if solc_version < Frontier.solc_min_version():
raise Exception("Unsupported solc version: {}".format(solc_version))
return solc_version
Loading

0 comments on commit 4ab1a93

Please sign in to comment.