diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 458742074e..a01e2c8964 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -62,7 +62,8 @@ jobs: - name: Run pypy3 tests run: tox -e pypy3 env: - PYPY_GC_MAX: "10G" + PYPY_GC_MAX: "2G" + PYPY_GC_MIN: "1G" json_infra: runs-on: [self-hosted-ghr, size-xl-x64] diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5cb1e62462..506f1a01e9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,6 +8,8 @@ In particular, we appreciate support in the following areas: - Fixing and responding to [issues](https://github.com/ethereum/execution-specs/issues), especially those tagged as [E-easy](https://github.com/ethereum/execution-specs/labels/E-easy) which are meant as introductory issues for external contributors. - Improving the documentation. +> [!IMPORTANT] +> Generally, we do not assign issues to external contributors. If you want to work on an issue, you are very welcome to go ahead and make a pull request. We would, hoever, be happy to answer questions you may have before you start implementing. For details about EELS usage and building, please refer the [README](https://github.com/ethereum/execution-specs/blob/master/README.md#usage) @@ -36,7 +38,7 @@ When creating pull requests affecting multiple forks, we recommended submitting 2. Apply the changes across the other forks, push them, and mark the pull request as ready for review. This saves you having to apply code review feedback repeatedly for each fork. - + ### Development Running the tests necessary to merge into the repository requires: @@ -82,7 +84,9 @@ Note: Make sure to run the EVM trace on a small number of tests at a time. The l Below is an example. ```bash -pytest tests/frontier/test_state_transition.py -k 'test_general_state_tests_new' --evm-trace +uv run --extra test \ + pytest 'tests/json_infra/test_state_tests.py::test_state_tests_frontier[stAttackTest - ContractCreationSpam - 0]' \ + --evm_trace ``` diff --git a/src/ethereum/forks/dao_fork/fork.py b/src/ethereum/forks/dao_fork/fork.py index d407639ab3..e0de96ff10 100644 --- a/src/ethereum/forks/dao_fork/fork.py +++ b/src/ethereum/forks/dao_fork/fork.py @@ -776,7 +776,7 @@ def calculate_block_difficulty( set for the genesis block since it has no parent. So, a block can't be less difficult than the genesis block, therefore each block's difficulty is set to the maximum value between the calculated - difficulty and the ``GENESIS_DIFFICULTY``. + difficulty and the ``MINIMUM_DIFFICULTY``. Parameters ---------- @@ -795,12 +795,15 @@ def calculate_block_difficulty( Computed difficulty for a block. """ - offset = ( - int(parent_difficulty) - // 2048 - * max(1 - int(block_timestamp - parent_timestamp) // 10, -99) - ) - difficulty = int(parent_difficulty) + offset + # Precompute helpers to avoid repeated int() conversions while + # keeping behavior. + + parent_difficulty_int = int(parent_difficulty) + time_delta = int(block_timestamp) - int(parent_timestamp) + + offset = (parent_difficulty_int // 2048) * max(1 - (time_delta // 10), -99) + difficulty = parent_difficulty_int + offset + # Historical Note: The difficulty bomb was not present in Ethereum at the # start of Frontier, but was added shortly after launch. However since the # bomb has no effect prior to block 200000 we pretend it existed from diff --git a/src/ethereum/forks/frontier/fork.py b/src/ethereum/forks/frontier/fork.py index e3c7183ae2..5b52c77084 100644 --- a/src/ethereum/forks/frontier/fork.py +++ b/src/ethereum/forks/frontier/fork.py @@ -743,13 +743,22 @@ def calculate_block_difficulty( """ Computes difficulty of a block using its header and parent header. - The difficulty of a block is determined by the time the block was created - after its parent. If a block's timestamp is more than 13 seconds after its - parent block then its difficulty is set as the difference between the - parent's difficulty and the ``max_adjustment_delta``. Otherwise, if the - time between parent and child blocks is too small (under 13 seconds) then, - to avoid mass forking, the block's difficulty is set to the sum of the - delta and the parent's difficulty. + The difficulty is determined by the time the block was created after its + parent. The ``offset`` is calculated using the parent block's difficulty, + ``parent_difficulty``, and the timestamp between blocks. This offset is + then added to the parent difficulty and is stored as the ``difficulty`` + variable. If the time between the block and its parent is too short, the + offset will result in a positive number thus making the sum of + ``parent_difficulty`` and ``offset`` to be a greater value in order to + avoid mass forking. But, if the time is long enough, then the offset + results in a negative value making the block less difficult than + its parent. + + The base standard for a block's difficulty is the predefined value + set for the genesis block since it has no parent. So, a block + can't be less difficult than the genesis block, therefore each block's + difficulty is set to the maximum value between the calculated + difficulty and the ``MINIMUM_DIFFICULTY``. Parameters ---------- @@ -768,11 +777,14 @@ def calculate_block_difficulty( Computed difficulty for a block. """ - max_adjustment_delta = parent_difficulty // Uint(2048) - if block_timestamp < parent_timestamp + U256(13): - difficulty = parent_difficulty + max_adjustment_delta - else: # block_timestamp >= parent_timestamp + 13 - difficulty = parent_difficulty - max_adjustment_delta + # Precompute helpers to avoid repeated int() conversions while + # keeping behavior. + + parent_difficulty_int = int(parent_difficulty) + time_delta = int(block_timestamp) - int(parent_timestamp) + + offset = (parent_difficulty_int // 2048) * max(1 - (time_delta // 10), -99) + difficulty = parent_difficulty_int + offset # Historical Note: The difficulty bomb was not present in Ethereum at the # start of Frontier, but was added shortly after launch. However since the @@ -781,9 +793,9 @@ def calculate_block_difficulty( # See https://github.com/ethereum/go-ethereum/pull/1588 num_bomb_periods = (int(block_number) // 100000) - 2 if num_bomb_periods >= 0: - difficulty += Uint(2**num_bomb_periods) + difficulty += 2**num_bomb_periods # Some clients raise the difficulty to `MINIMUM_DIFFICULTY` prior to adding # the bomb. This bug does not matter because the difficulty is always much # greater than `MINIMUM_DIFFICULTY` on Mainnet. - return max(difficulty, MINIMUM_DIFFICULTY) + return Uint(max(difficulty, int(MINIMUM_DIFFICULTY))) diff --git a/src/ethereum/forks/homestead/fork.py b/src/ethereum/forks/homestead/fork.py index 6d16c81936..5d9f286389 100644 --- a/src/ethereum/forks/homestead/fork.py +++ b/src/ethereum/forks/homestead/fork.py @@ -733,7 +733,6 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: return True - def calculate_block_difficulty( block_number: Uint, block_timestamp: U256, @@ -751,48 +750,38 @@ def calculate_block_difficulty( offset will result in a positive number thus making the sum of ``parent_difficulty`` and ``offset`` to be a greater value in order to avoid mass forking. But, if the time is long enough, then the offset - results in a negative value making the block less difficult than - its parent. - - The base standard for a block's difficulty is the predefined value - set for the genesis block since it has no parent. So, a block - can't be less difficult than the genesis block, therefore each block's - difficulty is set to the maximum value between the calculated - difficulty and the ``GENESIS_DIFFICULTY``. + results in a negative value making the block less difficult than its + parent. - Parameters - ---------- - block_number : - Block number of the block. - block_timestamp : - Timestamp of the block. - parent_timestamp : - Timestamp of the parent block. - parent_difficulty : - difficulty of the parent block. - - Returns - ------- - difficulty : `ethereum.base_types.Uint` - Computed difficulty for a block. + The base standard for a block's difficulty is the predefined value set for + the genesis block since it has no parent. So, a block can't be less + difficult than the genesis block, therefore each block's difficulty is set + to the maximum value between the calculated difficulty and the + ``MINIMUM_DIFFICULTY``. + Homestead difficulty: same behavior, fewer int() casts. """ - offset = ( - int(parent_difficulty) - // 2048 - * max(1 - int(block_timestamp - parent_timestamp) // 10, -99) + # Cast only when necessary for signed arithmetic, avoiding intermediate variables. + parent_difficulty_int = int(parent_difficulty) + time_delta = int(block_timestamp) - int(parent_timestamp) + + offset = (parent_difficulty_int // 2048) * max( + 1 - (time_delta // 10), + -99 ) - difficulty = int(parent_difficulty) + offset + difficulty = parent_difficulty_int + offset + # Historical Note: The difficulty bomb was not present in Ethereum at the # start of Frontier, but was added shortly after launch. However since the # bomb has no effect prior to block 200000 we pretend it existed from # genesis. # See https://github.com/ethereum/go-ethereum/pull/1588 + num_bomb_periods = (int(block_number) // 100000) - 2 if num_bomb_periods >= 0: difficulty += 2**num_bomb_periods - # Some clients raise the difficulty to `MINIMUM_DIFFICULTY` prior to adding - # the bomb. This bug does not matter because the difficulty is always much - # greater than `MINIMUM_DIFFICULTY` on Mainnet. - return Uint(max(difficulty, int(MINIMUM_DIFFICULTY))) + # Some clients raise the difficulty to MINIMUM_DIFFICULTY prior to adding + # the bomb. This bug does not matter because difficulty is always greater + # than MINIMUM_DIFFICULTY on Mainnet. + return Uint(max(difficulty, int(MINIMUM_DIFFICULTY))) \ No newline at end of file diff --git a/src/ethereum/forks/spurious_dragon/fork.py b/src/ethereum/forks/spurious_dragon/fork.py index 88872c4cb1..6ea60e9c1d 100644 --- a/src/ethereum/forks/spurious_dragon/fork.py +++ b/src/ethereum/forks/spurious_dragon/fork.py @@ -767,7 +767,7 @@ def calculate_block_difficulty( set for the genesis block since it has no parent. So, a block can't be less difficult than the genesis block, therefore each block's difficulty is set to the maximum value between the calculated - difficulty and the ``GENESIS_DIFFICULTY``. + difficulty and the ``MINIMUM_DIFFICULTY``. Parameters ---------- @@ -786,12 +786,15 @@ def calculate_block_difficulty( Computed difficulty for a block. """ - offset = ( - int(parent_difficulty) - // 2048 - * max(1 - int(block_timestamp - parent_timestamp) // 10, -99) - ) - difficulty = int(parent_difficulty) + offset + # Precompute helpers to avoid repeated int() conversions while + # keeping behavior. + + parent_difficulty_int = int(parent_difficulty) + time_delta = int(block_timestamp) - int(parent_timestamp) + + offset = (parent_difficulty_int // 2048) * max(1 - (time_delta // 10), -99) + difficulty = parent_difficulty_int + offset + # Historical Note: The difficulty bomb was not present in Ethereum at the # start of Frontier, but was added shortly after launch. However since the # bomb has no effect prior to block 200000 we pretend it existed from diff --git a/src/ethereum/forks/tangerine_whistle/fork.py b/src/ethereum/forks/tangerine_whistle/fork.py index 6d16c81936..5b52c77084 100644 --- a/src/ethereum/forks/tangerine_whistle/fork.py +++ b/src/ethereum/forks/tangerine_whistle/fork.py @@ -758,7 +758,7 @@ def calculate_block_difficulty( set for the genesis block since it has no parent. So, a block can't be less difficult than the genesis block, therefore each block's difficulty is set to the maximum value between the calculated - difficulty and the ``GENESIS_DIFFICULTY``. + difficulty and the ``MINIMUM_DIFFICULTY``. Parameters ---------- @@ -777,12 +777,15 @@ def calculate_block_difficulty( Computed difficulty for a block. """ - offset = ( - int(parent_difficulty) - // 2048 - * max(1 - int(block_timestamp - parent_timestamp) // 10, -99) - ) - difficulty = int(parent_difficulty) + offset + # Precompute helpers to avoid repeated int() conversions while + # keeping behavior. + + parent_difficulty_int = int(parent_difficulty) + time_delta = int(block_timestamp) - int(parent_timestamp) + + offset = (parent_difficulty_int // 2048) * max(1 - (time_delta // 10), -99) + difficulty = parent_difficulty_int + offset + # Historical Note: The difficulty bomb was not present in Ethereum at the # start of Frontier, but was added shortly after launch. However since the # bomb has no effect prior to block 200000 we pretend it existed from diff --git a/src/ethereum/utils/byte.py b/src/ethereum/utils/byte.py index e4bed22dab..f3e949a636 100644 --- a/src/ethereum/utils/byte.py +++ b/src/ethereum/utils/byte.py @@ -26,7 +26,7 @@ def left_pad_zero_bytes( value : The byte string that needs to be padded. size : - The number of bytes that need that need to be padded. + The number of bytes that need to be padded. Returns ------- @@ -48,7 +48,7 @@ def right_pad_zero_bytes( value : The byte string that needs to be padded. size : - The number of bytes that need that need to be padded. + The number of bytes that need to be padded. Returns ------- diff --git a/src/ethereum/utils/numeric.py b/src/ethereum/utils/numeric.py index 97026bc923..4233503fcd 100644 --- a/src/ethereum/utils/numeric.py +++ b/src/ethereum/utils/numeric.py @@ -42,7 +42,7 @@ def get_sign(value: int) -> int: def ceil32(value: Uint) -> Uint: """ - Converts a unsigned integer to the next closest multiple of 32. + Converts an unsigned integer to the next closest multiple of 32. Parameters ---------- diff --git a/src/ethereum_spec_tools/evm_tools/daemon.py b/src/ethereum_spec_tools/evm_tools/daemon.py index 87a2593fde..67ba3ede96 100644 --- a/src/ethereum_spec_tools/evm_tools/daemon.py +++ b/src/ethereum_spec_tools/evm_tools/daemon.py @@ -164,7 +164,7 @@ def __init__(self, options: argparse.Namespace) -> None: from platformdirs import user_runtime_dir except ImportError as e: raise Exception( - "Missing plaformdirs dependency (try installing " + "Missing platformdirs dependency (try installing " "ethereum[tools] extra)" ) from e runtime_dir = user_runtime_dir( diff --git a/tox.ini b/tox.ini index 7b093d6e14..de618d1c50 100644 --- a/tox.ini +++ b/tox.ini @@ -45,7 +45,7 @@ extras = commands = fill \ -m "not slow and not zkevm and not benchmark" \ - -n auto --maxprocesses 6 \ + -n auto --maxprocesses 10 --dist=loadgroup \ --basetemp="{temp_dir}/pytest" \ --clean \ --until Osaka \ @@ -56,13 +56,16 @@ extras = test,fill passenv = PYPY_GC_MAX + PYPY_GC_MIN commands = fill \ + --skip-index \ + --no-html \ --tb=no \ --show-capture=no \ --disable-warnings \ -m "not slow and not zkevm and not benchmark" \ - -n auto --maxprocesses 3 \ + -n auto --maxprocesses 7 --dist=loadgroup \ --basetemp="{temp_dir}/pytest" \ --clean \ --until Osaka \ @@ -74,6 +77,7 @@ extras = optimized passenv = PYPY_GC_MAX + PYPY_GC_MIN commands = pytest \ -m "not slow and not evm_tools" \