Skip to content
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
42 changes: 3 additions & 39 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -427,19 +427,6 @@ exclude = ["tests/fixtures/", "eest_tests/"]
ignore_names = ["pytest_*"]

[tool.ruff]
extend-exclude = [
".cache/",
".git/",
".pytest_cache/",
".ruff_cache/",
".tox/",
".venv/",
".vscode/",
"tests/fixtures/*",
"tests/json_infra/fixtures/*",
"eest_tests/*",
"vulture_whitelist.py",
]
line-length = 79

[tool.ruff.lint]
Expand All @@ -451,6 +438,7 @@ select = [
"I", # isort
"A", # flake8-builtins
"N", # pep8-naming
"D", # pydocstyle
"ARG", # flake8-unused-arguments
]
fixable = [
Expand All @@ -463,34 +451,14 @@ fixable = [
]
ignore = [
# Common to STEEL
"D205", # Missing blank line after summary
"D107", # Missing docstring in __init__
"D203", # 1 blank line required before class docstring
"D205", # Missing blank line after summary
"D212", # Multi-line docstring summary should start at the first line
"D415", # First line should end with a ".", "?", or "!"

# Specific to EELS
"D107", # Missing docstring in __init__
"D200", # One-line docstring should fit on one line with quotes
"D205", # 1 blank line required between summary and description
"D400", # First line should end with a period
"D401", # First line should be in imperative mood ("Do", not "Does")
"D410", # Missing blank line after last section (Args, Returns, Raises)
"D411", # Missing blank line before last section
"D412", # No blank lines between sections
"D413", # Missing blank line after last section (same as 410)
"D414", # Section should end with a period
"D416", # Section names should be in the correct order
"E203", # Whitespace before ':'
]

[tool.ruff.lint.per-file-ignores]
"tests/*" = [
"D100", # Missing docstring in public module
"D101", # Missing docstring in public class
"D103", # Missing docstring in public function
"D104", # Missing docstring in public package
"E501", # Line too long
]
"src/ethereum_spec_tools/evm_tools/loaders/fork_loader.py" = [
"N802" # Property names do not need to be lowercase
]
Expand All @@ -508,10 +476,6 @@ ignore = [
"N815" # The traces must use camel case in JSON property names
]

[tool.ruff.lint.mccabe]
# Set the maximum allowed cyclomatic complexity. C901 default is 10.
max-complexity = 7

[tool.codespell]
builtin = "clear,code,usage" # Built-in dictionaries to use
skip = [ # Don't check these files/folders
Expand Down
3 changes: 2 additions & 1 deletion src/ethereum/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
### Introduction
Introduction to Ethereum.

Seeing as internet connections have been vastly expanding across the
world, spreading information has become as cheap as ever. Bitcoin, for
Expand All @@ -16,6 +16,7 @@
This package contains a reference implementation, written as simply as
possible, to aid in defining the behavior of Ethereum clients.
"""

import sys

__version__ = "2.18.0rc2"
Expand Down
4 changes: 1 addition & 3 deletions src/ethereum/crypto/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
"""
Cryptographic primitives used in Ethereum.
"""
"""Cryptographic primitives used in Ethereum."""
32 changes: 14 additions & 18 deletions src/ethereum/crypto/blake2.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
"""
The Blake2 Implementation
^^^^^^^^^^^^^^^^^^^^^^^^^^
"""
"""The Blake2 Implementation."""

import struct
from dataclasses import dataclass
from typing import Final, List, Tuple
Expand All @@ -21,6 +19,7 @@ def spit_le_to_uint(data: bytes, start: int, num_words: int) -> List[Uint]:
Position to start the extraction
num_words:
The number of words to be extracted

"""
words = []
for i in range(num_words):
Expand Down Expand Up @@ -52,40 +51,38 @@ class Blake2:

@property
def max_word(self) -> Uint:
"""
Largest value for a given Blake2 flavor.
"""
"""Largest value for a given Blake2 flavor."""
return Uint(2) ** self.w

@property
def w_R1(self) -> Uint:
"""
(w - R1) value for a given Blake2 flavor.
Used in the function G
Used in the function G.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we ignoring D205? If we're going to mandate summaries, we should mandate the blank line as well.

Copy link
Member

@danceratopz danceratopz Sep 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought I'd check the consequence of enabling D205. This example errors:

    """
    Generate an index file (index.json) of all the fixtures in the specified
    directory.
    """

As the D checks seemingly expect that the summary is on a single line, i.e., it thinks "directory" is the description.

This makes no sense, but it fixes D205:

    """
    Generate an index file (index.json) of all the fixtures in the specified

    directory.
    """

I'm inclined to disable D200, but enable D205. But it's late and will re-visit tomorrow.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, enabling D205 gives 1241 errors. These would not be trivial to fix. We typically launch into multiline docstrings without a summary, so they'd have to re-written. It would result in nicer documentation though.

e.g.

"""
A small pytest plugin that shows the a concise help string that only contains
the options defined by the plugins defined in execution-spec-tests.
"""

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Funny example, needs fixing anyway 😆

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will need to be handled as part of the markdown conversion. See #671

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, it does need to be fixed but can be rolled into #671

"""
return self.w - self.R1

@property
def w_R2(self) -> Uint:
"""
(w - R2) value for a given Blake2 flavor.
Used in the function G
Used in the function G.
"""
return self.w - self.R2

@property
def w_R3(self) -> Uint:
"""
(w - R3) value for a given Blake2 flavor.
Used in the function G
Used in the function G.
"""
return self.w - self.R3

@property
def w_R4(self) -> Uint:
"""
(w - R4) value for a given Blake2 flavor.
Used in the function G
Used in the function G.
"""
return self.w - self.R4

Expand Down Expand Up @@ -126,9 +123,7 @@ def w_R4(self) -> Uint:

@property
def sigma_len(self) -> int:
"""
Length of the sigma parameter.
"""
"""Length of the sigma parameter."""
return len(self.sigma)

def get_blake2_parameters(self, data: bytes) -> Tuple:
Expand All @@ -140,6 +135,7 @@ def get_blake2_parameters(self, data: bytes) -> Tuple:
----------
data :
The bytes data that has been passed in the message.

"""
rounds = Uint.from_be_bytes(data[:4])
h = spit_le_to_uint(data, 4, 8)
Expand All @@ -153,8 +149,7 @@ def G(
self, v: List, a: Uint, b: Uint, c: Uint, d: Uint, x: Uint, y: Uint
) -> List:
"""
The mixing function used in Blake2
https://datatracker.ietf.org/doc/html/rfc7693#section-3.1
The mixing function used in Blake2.

Parameters
----------
Expand All @@ -164,6 +159,7 @@ def G(
Indexes within v of the words to be mixed.
x, y :
The two input words for the mixing.

"""
v[a] = (v[a] + v[b] + x) % self.max_word
v[d] = ((v[d] ^ v[a]) >> self.R1) ^ (
Expand Down Expand Up @@ -197,8 +193,7 @@ def compress(
f: bool,
) -> bytes:
"""
'F Compression' from section 3.2 of RFC 7693:
https://tools.ietf.org/html/rfc7693#section-3.2
'F Compression' from section 3.2 of RFC 7693.

Parameters
----------
Expand All @@ -212,6 +207,7 @@ def compress(
Offset counters. 2 unsigned 64-bit little-endian words
f:
The final block indicator flag. An 8-bit word

"""
# Initialize local work vector v[0..15]
v = [Uint(0)] * 16
Expand Down
9 changes: 4 additions & 5 deletions src/ethereum/crypto/elliptic_curve.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
"""
Elliptic Curves
^^^^^^^^^^^^^^^
"""
"""Elliptic Curves."""

import coincurve
from Crypto.Util.asn1 import DerSequence
Expand Down Expand Up @@ -45,6 +42,7 @@ def secp256k1_recover(r: U256, s: U256, v: U256, msg_hash: Hash32) -> Bytes:
-------
public_key : `ethereum.base_types.Bytes`
Recovered public key.

"""
is_square = pow(
pow(r, U256(3), SECP256K1P) + SECP256K1B,
Expand Down Expand Up @@ -114,8 +112,8 @@ def secp256r1_verify(

Raises
------

Raises an `InvalidSignatureError` if the signature is not valid.

"""
# Convert U256 to regular integers for DerSequence
r_int = int(r)
Expand Down Expand Up @@ -152,6 +150,7 @@ def is_on_curve_secp256r1(x: U256, y: U256) -> bool:
-------
bool
True if the point is on the curve, False otherwise

"""
# Convert U256 to int for calculations
x_int = int(x)
Expand Down
5 changes: 3 additions & 2 deletions src/ethereum/crypto/hash.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"""
Cryptographic Hash Functions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Cryptographic Hash Functions.

.. contents:: Table of Contents
:backlinks: none
Expand Down Expand Up @@ -32,6 +31,7 @@ def keccak256(buffer: Bytes | bytearray) -> Hash32:
-------
hash : `ethereum.base_types.Hash32`
Output of the hash function.

"""
k = keccak.new(digest_bits=256)
return Hash32(k.update(buffer).digest())
Expand All @@ -50,6 +50,7 @@ def keccak512(buffer: Bytes | bytearray) -> Hash64:
-------
hash : `ethereum.base_types.Hash32`
Output of the hash function.

"""
k = keccak.new(digest_bits=512)
return Hash64(k.update(buffer).digest())
24 changes: 7 additions & 17 deletions src/ethereum/crypto/kzg.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
"""
The KZG Implementation
^^^^^^^^^^^^^^^^^^^^^^
"""
"""The KZG Implementation."""

from hashlib import sha256
from typing import Tuple

Expand Down Expand Up @@ -36,7 +34,7 @@ class KZGCommitment(Bytes48):


class KZGProof(Bytes48):
"""KZG proof"""
"""KZG proof."""

pass

Expand Down Expand Up @@ -67,9 +65,7 @@ class VersionedHash(Bytes32):
def kzg_commitment_to_versioned_hash(
kzg_commitment: KZGCommitment,
) -> VersionedHash:
"""
Convert a KZG commitment to a versioned hash.
"""
"""Convert a KZG commitment to a versioned hash."""
return VersionedHash(
VERSIONED_HASH_VERSION_KZG
+ Bytes32(sha256(kzg_commitment).digest())[1:]
Expand All @@ -88,9 +84,7 @@ def validate_kzg_g1(b: Bytes48) -> None:


def bytes_to_kzg_commitment(b: Bytes48) -> KZGCommitment:
"""
Convert untrusted bytes into a trusted and validated KZGCommitment.
"""
"""Convert untrusted bytes into a trusted and validated KZGCommitment."""
validate_kzg_g1(b)
return KZGCommitment(b)

Expand All @@ -107,17 +101,13 @@ def bytes_to_bls_field(b: Bytes32) -> BLSFieldElement:


def bytes_to_kzg_proof(b: Bytes48) -> KZGProof:
"""
Convert untrusted bytes into a trusted and validated KZGProof.
"""
"""Convert untrusted bytes into a trusted and validated KZGProof."""
validate_kzg_g1(b)
return KZGProof(b)


def pairing_check(values: Tuple[Tuple[FQ, FQ2], Tuple[FQ, FQ2]]) -> bool:
"""
Check if the pairings are valid.
"""
"""Check if the pairings are valid."""
p_q_1, p_q_2 = values
final_exponentiation = final_exponentiate(
pairing(p_q_1[1], p_q_1[0], final_exponentiate=False)
Expand Down
26 changes: 7 additions & 19 deletions src/ethereum/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,31 +1,23 @@
"""
Error types common across all Ethereum forks.
"""
"""Error types common across all Ethereum forks."""


class EthereumException(Exception): # noqa N818
class EthereumException(Exception): # noqa N818
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we want it to read EthereumException rather than EthereumError?

"""
Base class for all exceptions _expected_ to be thrown during normal
operation.
"""


class InvalidBlock(EthereumException):
"""
Thrown when a block being processed is found to be invalid.
"""
"""Thrown when a block being processed is found to be invalid."""


class StateWithEmptyAccount(EthereumException):
"""
Thrown when the state has empty account.
"""
"""Thrown when the state has empty account."""


class InvalidTransaction(EthereumException):
"""
Thrown when a transaction being processed is found to be invalid.
"""
"""Thrown when a transaction being processed is found to be invalid."""


class InvalidSenderError(InvalidTransaction):
Expand All @@ -36,9 +28,7 @@ class InvalidSenderError(InvalidTransaction):


class InvalidSignatureError(InvalidTransaction):
"""
Thrown when a transaction has an invalid signature.
"""
"""Thrown when a transaction has an invalid signature."""


class InsufficientBalanceError(InvalidTransaction):
Expand Down Expand Up @@ -70,6 +60,4 @@ class InsufficientTransactionGasError(InvalidTransaction):


class NonceOverflowError(InvalidTransaction):
"""
Thrown when a transaction's nonce is greater than `2**64 - 2`.
"""
"""Thrown when a transaction's nonce is greater than `2**64 - 2`."""
Loading
Loading