Skip to content

Conversation

@frangio
Copy link

@frangio frangio commented Jan 31, 2025

closes #817

For discussion. I'd personally find this very useful.

What was wrong?

Navigating to the latest specs requires knowing the fork name. Even though this information is available in the repo, it can be slow to remember and find in the list.

How was it fixed?

A symlink called latest was added.

Cute Animal Picture

image

@SamWilsn
Copy link
Contributor

Looks like this closes #817.

Apparently you can from ethereum import latest in Python, which is interesting. Means that this would probably interact with our versioning scheme. Simplest fix would be to say that imports from latest are not guaranteed to remain stable across HARDFORK version bumps?

@SamWilsn
Copy link
Contributor

Note that if we do decide to go forward with this, we'll need to:

  • Add the file to setup.cfg.
  • Add a lint that ensures the symlink is always pointing to the latest fork.
  • Document the symlink in RELEASING.md.

@frangio
Copy link
Author

frangio commented Feb 26, 2025

  • Add a lint that ensures the symlink is always pointing to the latest fork.

What should I use as the source of truth for what is the latest fork?

@SamWilsn
Copy link
Contributor

Hardfork.discover returns an ordered list.

Let me get a vibe check from @gurukamath and @petertdavies before you put in too much work. Personally, I don't have any objections offhand.

@gurukamath
Copy link
Contributor

gurukamath commented Feb 26, 2025

Let me get a vibe check from @gurukamath and @petertdavies before you put in too much work. Personally, I don't have any objections offhand.

With the understanding that the latest here means the most recent fork to be live on mainnet, I'm in favour of this with a lint in place.

@SamWilsn
Copy link
Contributor

SamWilsn commented Feb 26, 2025

Let's go ahead with this. If you're willing to work on it @frangio, by all means do. Otherwise, we'll get around to it.

@SamWilsn
Copy link
Contributor

Unfortunately it seems like pip/setuptools don't support symlinks. It might be possible to emulate this with a post-deploy hook, but that wouldn't show up in the repository itself, so less useful.

If we ever come back to this, here's a lint:

"""
Latest Symlink
^^^^^^^^^^^^^^

Ensures that the `latest` symlink points to the latest hardfork.
"""
from pathlib import Path
from typing import List, Sequence

from ethereum_spec_tools.forks import Hardfork
from ethereum_spec_tools.lint import Diagnostic, Lint


class LatestSymlink(Lint):
    """
    Ensures that the `latest` symlink poins to the latest hardfork.
    """

    def lint(
        self, forks: List[Hardfork], position: int
    ) -> Sequence[Diagnostic]:
        """
        Reads the path of the `latest` symlink and compares it to the latest
        hardfork.
        """
        if position != len(forks) - 1:
            return []

        fork = forks[position]
        assert fork.path is not None

        fork_path = Path(fork.path)
        symlink_path = fork_path.parent.joinpath("latest")

        # Use `readlink` instead of `resolve` because there should only ever be
        # one symlink in the chain.
        try:
            print(symlink_path)
            target_path = symlink_path.readlink()
        except FileNotFoundError:
            return [Diagnostic("The latest symlink is missing.")]

        if target_path.is_absolute():
            return [Diagnostic("The latest symlink is not relative.")]

        if len(target_path.parts) != 1:
            return [Diagnostic("The latest symlink is not relative to forks.")]

        target_path = fork_path.parent.joinpath(target_path)

        if not symlink_path.is_symlink():
            return [Diagnostic("The latest pointer is not a symlink.")]

        if target_path.is_symlink():
            return [Diagnostic("The latest symlink target is also a symlink.")]

        target_path = target_path.resolve()
        fork_path = fork_path.resolve()

        if target_path == fork_path:
            return []

        fork_path = fork_path.relative_to(fork_path.parent)
        target_path = target_path.relative_to(target_path.parent)
        return [
            Diagnostic(
                f"The latest symlink should point to `{fork_path}` "
                f"(but points to `{target_path}` instead)."
            )
        ]

@SamWilsn SamWilsn closed this May 20, 2025
@frangio
Copy link
Author

frangio commented May 20, 2025

FWIW, my motivation for this PR was to have a quick way to navigate to the latest spec in the repo, on GitHub. I still think that would be valuable in some form. It could be via symlinks (even if not supported in import paths in Python), or it could be by adding direct links in the readme.

Carsons-Eels pushed a commit to Carsons-Eels/execution-specs that referenced this pull request Oct 16, 2025
* feat(forks): Adds `supports_blobs` method

* fix(forks): Transition fork comparisons

* refactor,fix(plugins/forks): `fork_transition_test` marker

* docs: add documentation, changelog

* refactor(plugins/forks): Validity markers as classes

* fix: fork set handling

* fix(plugins): config variable usage in other plugins

* fix(plugins/forks): Self-documenting code for validity marker classes

* whitelist

* refactor(forks): suggestions for fork transition marker changes (ethereum#1104)

* refactor(forks): make `name()` an abstractmethod

* refactor(forks): add helper methods to simplify fork comparisons

* Update src/pytest_plugins/forks/forks.py

Co-authored-by: danceratopz <danceratopz@gmail.com>

* Update src/pytest_plugins/forks/forks.py

Co-authored-by: danceratopz <danceratopz@gmail.com>

* Update src/pytest_plugins/forks/forks.py

Co-authored-by: danceratopz <danceratopz@gmail.com>

* fixup

---------

Co-authored-by: danceratopz <danceratopz@gmail.com>
danceratopz added a commit to danceratopz/execution-specs that referenced this pull request Oct 22, 2025
* feat(forks): Adds `supports_blobs` method

* fix(forks): Transition fork comparisons

* refactor,fix(plugins/forks): `fork_transition_test` marker

* docs: add documentation, changelog

* refactor(plugins/forks): Validity markers as classes

* fix: fork set handling

* fix(plugins): config variable usage in other plugins

* fix(plugins/forks): Self-documenting code for validity marker classes

* whitelist

* refactor(forks): suggestions for fork transition marker changes (ethereum#1104)

* refactor(forks): make `name()` an abstractmethod

* refactor(forks): add helper methods to simplify fork comparisons

* Update src/pytest_plugins/forks/forks.py

Co-authored-by: danceratopz <danceratopz@gmail.com>

* Update src/pytest_plugins/forks/forks.py

Co-authored-by: danceratopz <danceratopz@gmail.com>

* Update src/pytest_plugins/forks/forks.py

Co-authored-by: danceratopz <danceratopz@gmail.com>

* fixup

---------

Co-authored-by: danceratopz <danceratopz@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Idea: "latest" directory to always hold latest fork

3 participants