Skip to content

Ethereum Test Base Types package

Common definitions and types.

Address

Bases: FixedSizeBytes[20]

Class that helps represent Ethereum addresses in tests.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
class Address(FixedSizeBytes[20]):  # type: ignore
    """Class that helps represent Ethereum addresses in tests."""

    label: str | None = None

    def __new__(
        cls,
        input_bytes: "FixedSizeBytesConvertible | Address",
        *args: Any,
        label: str | None = None,
        **kwargs: Any,
    ) -> Self:
        """Create a new Address object with an optional label."""
        instance = super(Address, cls).__new__(
            cls, input_bytes, *args, **kwargs
        )
        if isinstance(input_bytes, Address) and label is None:
            instance.label = input_bytes.label
        else:
            instance.label = label
        return instance

__new__(input_bytes, *args, label=None, **kwargs)

Create a new Address object with an optional label.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
def __new__(
    cls,
    input_bytes: "FixedSizeBytesConvertible | Address",
    *args: Any,
    label: str | None = None,
    **kwargs: Any,
) -> Self:
    """Create a new Address object with an optional label."""
    instance = super(Address, cls).__new__(
        cls, input_bytes, *args, **kwargs
    )
    if isinstance(input_bytes, Address) and label is None:
        instance.label = input_bytes.label
    else:
        instance.label = label
    return instance

Bloom

Bases: FixedSizeBytes[256]

Class that helps represent blooms in tests.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
467
468
469
470
class Bloom(FixedSizeBytes[256]):  # type: ignore
    """Class that helps represent blooms in tests."""

    pass

BLSPublicKey

Bases: FixedSizeBytes[48]

Class that helps represent BLS public keys in tests.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
479
480
481
482
class BLSPublicKey(FixedSizeBytes[48]):  # type: ignore
    """Class that helps represent BLS public keys in tests."""

    pass

BLSSignature

Bases: FixedSizeBytes[96]

Class that helps represent BLS signatures in tests.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
485
486
487
488
class BLSSignature(FixedSizeBytes[96]):  # type: ignore
    """Class that helps represent BLS signatures in tests."""

    pass

Bytes

Bases: bytes, ToStringSchema

Class that helps represent bytes of variable length in tests.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
class Bytes(bytes, ToStringSchema):
    """Class that helps represent bytes of variable length in tests."""

    def __new__(cls, input_bytes: BytesConvertible = b"") -> Self:
        """Create a new Bytes object."""
        if type(input_bytes) is cls:
            return input_bytes
        return super(Bytes, cls).__new__(cls, to_bytes(input_bytes))

    __hash__ = bytes.__hash__

    def __str__(self) -> str:
        """Return the hexadecimal representation of the bytes."""
        return self.hex()

    def hex(self, *args: Any, **kwargs: Any) -> str:
        """Return the hexadecimal representation of the bytes."""
        return "0x" + super().hex(*args, **kwargs)

    def keccak256(self) -> "Hash":
        """Return the keccak256 hash of the opcode byte representation."""
        # Imported lazily so that merely importing the test framework does not
        # import the `ethereum` package: on xdist workers that import would
        # happen before pytest-cov starts the worker's coverage session,
        # making coverage report `ethereum` as "module-not-measured".
        from ethereum.crypto.hash import keccak256 as _keccak256

        return Hash(_keccak256(self))

    def sha256(self) -> "Hash":
        """Return the sha256 hash of the opcode byte representation."""
        return Hash(sha256(self).digest())

    @staticmethod
    def __get_pydantic_core_schema__(
        source_type: Any, handler: GetCoreSchemaHandler
    ) -> PlainValidatorFunctionSchema:
        """
        Call the class constructor without info and appends the serialization
        schema.
        """
        return no_info_plain_validator_function(
            source_type,
            serialization=to_string_ser_schema(),
            json_schema_input_schema=handler(
                Annotated[
                    str, StringConstraints(pattern=r"^0x([0-9a-fA-F]{2})*$")
                ]
            ),
        )

__new__(input_bytes=b'')

Create a new Bytes object.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
183
184
185
186
187
def __new__(cls, input_bytes: BytesConvertible = b"") -> Self:
    """Create a new Bytes object."""
    if type(input_bytes) is cls:
        return input_bytes
    return super(Bytes, cls).__new__(cls, to_bytes(input_bytes))

__str__()

Return the hexadecimal representation of the bytes.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
191
192
193
def __str__(self) -> str:
    """Return the hexadecimal representation of the bytes."""
    return self.hex()

hex(*args, **kwargs)

Return the hexadecimal representation of the bytes.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
195
196
197
def hex(self, *args: Any, **kwargs: Any) -> str:
    """Return the hexadecimal representation of the bytes."""
    return "0x" + super().hex(*args, **kwargs)

keccak256()

Return the keccak256 hash of the opcode byte representation.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
199
200
201
202
203
204
205
206
207
def keccak256(self) -> "Hash":
    """Return the keccak256 hash of the opcode byte representation."""
    # Imported lazily so that merely importing the test framework does not
    # import the `ethereum` package: on xdist workers that import would
    # happen before pytest-cov starts the worker's coverage session,
    # making coverage report `ethereum` as "module-not-measured".
    from ethereum.crypto.hash import keccak256 as _keccak256

    return Hash(_keccak256(self))

sha256()

Return the sha256 hash of the opcode byte representation.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
209
210
211
def sha256(self) -> "Hash":
    """Return the sha256 hash of the opcode byte representation."""
    return Hash(sha256(self).digest())

__get_pydantic_core_schema__(source_type, handler) staticmethod

Call the class constructor without info and appends the serialization schema.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
@staticmethod
def __get_pydantic_core_schema__(
    source_type: Any, handler: GetCoreSchemaHandler
) -> PlainValidatorFunctionSchema:
    """
    Call the class constructor without info and appends the serialization
    schema.
    """
    return no_info_plain_validator_function(
        source_type,
        serialization=to_string_ser_schema(),
        json_schema_input_schema=handler(
            Annotated[
                str, StringConstraints(pattern=r"^0x([0-9a-fA-F]{2})*$")
            ]
        ),
    )

BytesConcatenation

Bases: SupportsBytes, Sized

A class that can be concatenated with bytes.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
247
248
249
250
251
252
253
254
255
256
257
258
259
260
class BytesConcatenation(SupportsBytes, Sized, metaclass=ABCMeta):
    """A class that can be concatenated with bytes."""

    def __len__(self) -> int:
        """Return length of the object when converted to bytes."""
        return len(bytes(self))

    def __add__(self, other: bytes | SupportsBytes) -> bytes:
        """Concatenates the object with another bytes object."""
        return bytes(self) + bytes(other)

    def __radd__(self, other: bytes | SupportsBytes) -> bytes:
        """Concatenates the object with another bytes object."""
        return bytes(other) + bytes(self)

__len__()

Return length of the object when converted to bytes.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
250
251
252
def __len__(self) -> int:
    """Return length of the object when converted to bytes."""
    return len(bytes(self))

__add__(other)

Concatenates the object with another bytes object.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
254
255
256
def __add__(self, other: bytes | SupportsBytes) -> bytes:
    """Concatenates the object with another bytes object."""
    return bytes(self) + bytes(other)

__radd__(other)

Concatenates the object with another bytes object.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
258
259
260
def __radd__(self, other: bytes | SupportsBytes) -> bytes:
    """Concatenates the object with another bytes object."""
    return bytes(other) + bytes(self)

CoerceBytes

Bases: Bytes

Class that helps represent bytes of variable length in tests and supports removing white spaces anywhere in the string.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
232
233
234
235
236
237
238
239
240
241
242
243
244
class CoerceBytes(Bytes):
    """
    Class that helps represent bytes of variable length in tests and
    supports removing white spaces anywhere in the string.
    """

    def __new__(cls, input_bytes: BytesConvertible = b"") -> Self:
        """Create a new CoerceBytes object."""
        if type(input_bytes) is cls:
            return input_bytes
        if isinstance(input_bytes, str):
            input_bytes = sub(r"\s+", "", input_bytes)
        return super(Bytes, cls).__new__(cls, to_bytes(input_bytes))

__new__(input_bytes=b'')

Create a new CoerceBytes object.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
238
239
240
241
242
243
244
def __new__(cls, input_bytes: BytesConvertible = b"") -> Self:
    """Create a new CoerceBytes object."""
    if type(input_bytes) is cls:
        return input_bytes
    if isinstance(input_bytes, str):
        input_bytes = sub(r"\s+", "", input_bytes)
    return super(Bytes, cls).__new__(cls, to_bytes(input_bytes))

FixedSizeBytes

Bases: Bytes

Class that helps represent bytes of fixed length in tests.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
class FixedSizeBytes(Bytes):
    """Class that helps represent bytes of fixed length in tests."""

    byte_length: ClassVar[int]
    _sized_: ClassVar[Type["FixedSizeBytes"]]

    def __class_getitem__(cls, length: int) -> Type["FixedSizeBytes"]:
        """Create a new FixedSizeBytes class with the given length."""

        class Sized(cls):  # type: ignore
            byte_length = length

        Sized._sized_ = Sized
        return Sized

    def __new__(
        cls,
        input_bytes: FixedSizeBytesConvertible | Self,
        *,
        left_padding: bool = False,
        right_padding: bool = False,
    ) -> Self:
        """Create a new FixedSizeBytes object."""
        if type(input_bytes) is cls:
            return input_bytes
        return super(FixedSizeBytes, cls).__new__(
            cls,
            to_fixed_size_bytes(
                input_bytes,
                cls.byte_length,
                left_padding=left_padding,
                right_padding=right_padding,
            ),
        )

    # Defining `__eq__` drops the inherited hash, so restore the C one.
    __hash__ = bytes.__hash__

    def __eq__(self, other: object) -> bool:
        """Compare two FixedSizeBytes objects to be equal."""
        if other is None:
            return False
        if not isinstance(other, FixedSizeBytes):
            if not (
                isinstance(other, str)
                or isinstance(other, int)
                or isinstance(other, bytes)
                or isinstance(other, SupportsBytes)
            ):
                return False
            other = self._sized_(other)
        return super().__eq__(other)

    def __ne__(self, other: object) -> bool:
        """Compare two FixedSizeBytes objects to be not equal."""
        return not self.__eq__(other)

    @classmethod
    def __get_pydantic_core_schema__(
        cls, source_type: Any, handler: GetCoreSchemaHandler
    ) -> PlainValidatorFunctionSchema:
        """
        Call the class constructor without info and appends the serialization
        schema.
        """
        pattern = f"^0x([0-9a-fA-F]{{{cls.byte_length * 2}}})*$"
        return no_info_plain_validator_function(
            source_type,
            serialization=to_string_ser_schema(),
            json_schema_input_schema=handler(
                Annotated[str, StringConstraints(pattern=pattern)]
            ),
        )

__class_getitem__(length)

Create a new FixedSizeBytes class with the given length.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
342
343
344
345
346
347
348
349
def __class_getitem__(cls, length: int) -> Type["FixedSizeBytes"]:
    """Create a new FixedSizeBytes class with the given length."""

    class Sized(cls):  # type: ignore
        byte_length = length

    Sized._sized_ = Sized
    return Sized

__new__(input_bytes, *, left_padding=False, right_padding=False)

Create a new FixedSizeBytes object.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
def __new__(
    cls,
    input_bytes: FixedSizeBytesConvertible | Self,
    *,
    left_padding: bool = False,
    right_padding: bool = False,
) -> Self:
    """Create a new FixedSizeBytes object."""
    if type(input_bytes) is cls:
        return input_bytes
    return super(FixedSizeBytes, cls).__new__(
        cls,
        to_fixed_size_bytes(
            input_bytes,
            cls.byte_length,
            left_padding=left_padding,
            right_padding=right_padding,
        ),
    )

__eq__(other)

Compare two FixedSizeBytes objects to be equal.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
374
375
376
377
378
379
380
381
382
383
384
385
386
387
def __eq__(self, other: object) -> bool:
    """Compare two FixedSizeBytes objects to be equal."""
    if other is None:
        return False
    if not isinstance(other, FixedSizeBytes):
        if not (
            isinstance(other, str)
            or isinstance(other, int)
            or isinstance(other, bytes)
            or isinstance(other, SupportsBytes)
        ):
            return False
        other = self._sized_(other)
    return super().__eq__(other)

__ne__(other)

Compare two FixedSizeBytes objects to be not equal.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
389
390
391
def __ne__(self, other: object) -> bool:
    """Compare two FixedSizeBytes objects to be not equal."""
    return not self.__eq__(other)

__get_pydantic_core_schema__(source_type, handler) classmethod

Call the class constructor without info and appends the serialization schema.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
@classmethod
def __get_pydantic_core_schema__(
    cls, source_type: Any, handler: GetCoreSchemaHandler
) -> PlainValidatorFunctionSchema:
    """
    Call the class constructor without info and appends the serialization
    schema.
    """
    pattern = f"^0x([0-9a-fA-F]{{{cls.byte_length * 2}}})*$"
    return no_info_plain_validator_function(
        source_type,
        serialization=to_string_ser_schema(),
        json_schema_input_schema=handler(
            Annotated[str, StringConstraints(pattern=pattern)]
        ),
    )

ForkHash

Bases: FixedSizeBytes[4]

Class that helps represent the CRC config hashes and identifiers of a fork.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
411
412
413
414
415
416
class ForkHash(FixedSizeBytes[4]):  # type: ignore
    """
    Class that helps represent the CRC config hashes and identifiers of a fork.
    """

    pass

Hash

Bases: FixedSizeBytes[32]

Class that helps represent hashes in tests.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
442
443
444
445
class Hash(FixedSizeBytes[32]):  # type: ignore
    """Class that helps represent hashes in tests."""

    pass

HashInt

Bases: FixedSizeHexNumber[32]

Class that helps represent hashes in tests.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
330
331
332
333
class HashInt(FixedSizeHexNumber[32]):  # type: ignore
    """Class that helps represent hashes in tests."""

    pass

HeaderNonce

Bases: FixedSizeBytes[8]

Class that helps represent the header nonce in tests.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
473
474
475
476
class HeaderNonce(FixedSizeBytes[8]):  # type: ignore
    """Class that helps represent the header nonce in tests."""

    pass

HexNumber

Bases: Number

Class that helps represent hexadecimal numbers in tests.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
class HexNumber(Number):
    """Class that helps represent hexadecimal numbers in tests."""

    def __str__(self) -> str:
        """Return the string representation of the number."""
        return self.hex()

    @staticmethod
    def __get_pydantic_core_schema__(
        source_type: Any, handler: GetCoreSchemaHandler
    ) -> PlainValidatorFunctionSchema:
        """
        Call the class constructor without info and appends the serialization
        schema.
        """
        return no_info_plain_validator_function(
            source_type,
            serialization=to_string_ser_schema(),
            json_schema_input_schema=handler(
                Annotated[str, StringConstraints(pattern=r"^0x[0-9a-fA-F]*$")]
            ),
        )

__str__()

Return the string representation of the number.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
123
124
125
def __str__(self) -> str:
    """Return the string representation of the number."""
    return self.hex()

__get_pydantic_core_schema__(source_type, handler) staticmethod

Call the class constructor without info and appends the serialization schema.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
@staticmethod
def __get_pydantic_core_schema__(
    source_type: Any, handler: GetCoreSchemaHandler
) -> PlainValidatorFunctionSchema:
    """
    Call the class constructor without info and appends the serialization
    schema.
    """
    return no_info_plain_validator_function(
        source_type,
        serialization=to_string_ser_schema(),
        json_schema_input_schema=handler(
            Annotated[str, StringConstraints(pattern=r"^0x[0-9a-fA-F]*$")]
        ),
    )

Number

Bases: int, ToStringSchema

Class that helps represent numbers in tests.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
54
55
56
57
58
59
60
61
62
63
64
65
66
67
class Number(int, ToStringSchema):
    """Class that helps represent numbers in tests."""

    def __new__(cls, input_number: NumberConvertible | Self) -> Self:
        """Create a new Number object."""
        return super(Number, cls).__new__(cls, to_number(input_number))

    def __str__(self) -> str:
        """Return the string representation of the number."""
        return str(int(self))

    def hex(self) -> str:
        """Return the hexadecimal representation of the number."""
        return hex(self)

__new__(input_number)

Create a new Number object.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
57
58
59
def __new__(cls, input_number: NumberConvertible | Self) -> Self:
    """Create a new Number object."""
    return super(Number, cls).__new__(cls, to_number(input_number))

__str__()

Return the string representation of the number.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
61
62
63
def __str__(self) -> str:
    """Return the string representation of the number."""
    return str(int(self))

hex()

Return the hexadecimal representation of the number.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
65
66
67
def hex(self) -> str:
    """Return the hexadecimal representation of the number."""
    return hex(self)

StorageKey

Bases: FixedSizeBytes[32]

Storage key type that automatically applies left padding for values shorter than 32 bytes.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
class StorageKey(FixedSizeBytes[32]):  # type: ignore
    """
    Storage key type that automatically applies left padding for values shorter
    than 32 bytes.
    """

    def __new__(
        cls,
        input_bytes: FixedSizeBytesConvertible | FixedSizeBytes,
        **kwargs: Any,
    ) -> Self:
        """Create a new StorageKey with automatic left padding."""
        # Always apply left_padding for storage keys unless explicitly set to
        # False
        if "left_padding" not in kwargs:
            kwargs["left_padding"] = True
        return super().__new__(cls, input_bytes, **kwargs)

__new__(input_bytes, **kwargs)

Create a new StorageKey with automatic left padding.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
454
455
456
457
458
459
460
461
462
463
464
def __new__(
    cls,
    input_bytes: FixedSizeBytesConvertible | FixedSizeBytes,
    **kwargs: Any,
) -> Self:
    """Create a new StorageKey with automatic left padding."""
    # Always apply left_padding for storage keys unless explicitly set to
    # False
    if "left_padding" not in kwargs:
        kwargs["left_padding"] = True
    return super().__new__(cls, input_bytes, **kwargs)

Wei

Bases: Number

Class that helps represent wei that can be parsed from strings.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
class Wei(Number):
    """Class that helps represent wei that can be parsed from strings."""

    def __new__(cls, input_number: NumberConvertible | Self) -> Self:
        """Create a new Number object."""
        if isinstance(input_number, str):
            words = input_number.split()
            multiplier = 1
            assert len(words) <= 2
            value_str = words[0]
            if len(words) > 1:
                unit = words[1].lower()
                multiplier = cls._get_multiplier(unit)
            value: float
            if "**" in value_str:
                base, exp = value_str.split("**")
                value = float(base) ** int(exp)
            else:
                value = (
                    int(value_str)
                    if value_str.isdecimal()
                    else float(value_str)
                )
            return super(Number, cls).__new__(cls, value * multiplier)
        return super(Number, cls).__new__(cls, to_number(input_number))

    @staticmethod
    def _get_multiplier(unit: str) -> int:
        """
        Return the multiplier for the given unit of wei, handling synonyms.
        """
        match unit:
            case "wei":
                return 1
            case "kwei" | "babbage" | "femtoether":
                return 10**3
            case "mwei" | "lovelace" | "picoether":
                return 10**6
            case "gwei" | "shannon" | "nanoether" | "nano":
                return 10**9
            case "szabo" | "microether" | "micro":
                return 10**12
            case "finney" | "milliether" | "milli":
                return 10**15
            case "ether" | "eth":
                return 10**18
            case _:
                raise ValueError(f"Invalid unit {unit}")

__new__(input_number)

Create a new Number object.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
def __new__(cls, input_number: NumberConvertible | Self) -> Self:
    """Create a new Number object."""
    if isinstance(input_number, str):
        words = input_number.split()
        multiplier = 1
        assert len(words) <= 2
        value_str = words[0]
        if len(words) > 1:
            unit = words[1].lower()
            multiplier = cls._get_multiplier(unit)
        value: float
        if "**" in value_str:
            base, exp = value_str.split("**")
            value = float(base) ** int(exp)
        else:
            value = (
                int(value_str)
                if value_str.isdecimal()
                else float(value_str)
            )
        return super(Number, cls).__new__(cls, value * multiplier)
    return super(Number, cls).__new__(cls, to_number(input_number))

ZeroPaddedHexNumber

Bases: HexNumber

Class that helps represent zero padded hexadecimal numbers in tests.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
class ZeroPaddedHexNumber(HexNumber):
    """Class that helps represent zero padded hexadecimal numbers in tests."""

    def hex(self) -> str:
        """Return the hexadecimal representation of the number."""
        if self == 0:
            return "0x00"
        hex_str = hex(self)[2:]
        if len(hex_str) % 2 == 1:
            return "0x0" + hex_str
        return "0x" + hex_str

    @staticmethod
    def __get_pydantic_core_schema__(
        source_type: Any, handler: GetCoreSchemaHandler
    ) -> PlainValidatorFunctionSchema:
        """
        Call the class constructor without info and appends the serialization
        schema.
        """
        return no_info_plain_validator_function(
            source_type,
            serialization=to_string_ser_schema(),
            json_schema_input_schema=handler(
                Annotated[
                    str, StringConstraints(pattern=r"^0x([0-9a-fA-F]{2})*$")
                ]
            ),
        )

hex()

Return the hexadecimal representation of the number.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
147
148
149
150
151
152
153
154
def hex(self) -> str:
    """Return the hexadecimal representation of the number."""
    if self == 0:
        return "0x00"
    hex_str = hex(self)[2:]
    if len(hex_str) % 2 == 1:
        return "0x0" + hex_str
    return "0x" + hex_str

__get_pydantic_core_schema__(source_type, handler) staticmethod

Call the class constructor without info and appends the serialization schema.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
@staticmethod
def __get_pydantic_core_schema__(
    source_type: Any, handler: GetCoreSchemaHandler
) -> PlainValidatorFunctionSchema:
    """
    Call the class constructor without info and appends the serialization
    schema.
    """
    return no_info_plain_validator_function(
        source_type,
        serialization=to_string_ser_schema(),
        json_schema_input_schema=handler(
            Annotated[
                str, StringConstraints(pattern=r"^0x([0-9a-fA-F]{2})*$")
            ]
        ),
    )

to_json(input_model)

Convert a model to its json data representation.

Source code in packages/testing/src/execution_testing/base_types/base_types_json.py
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
def to_json(
    input_model: (
        EthereumTestBaseModel
        | EthereumTestRootModel
        | AnyStr
        | List[EthereumTestBaseModel | EthereumTestRootModel | AnyStr]
    ),
) -> Any:
    """Convert a model to its json data representation."""
    if isinstance(input_model, list):
        return [to_json(item) for item in input_model]
    elif isinstance(
        input_model, (EthereumTestBaseModel, EthereumTestRootModel)
    ):
        return input_model.model_dump(
            mode="json", by_alias=True, exclude_none=True
        )
    else:
        return str(input_model)

AccessList

Bases: CamelModel, RLPSerializable

Access List for transactions.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
429
430
431
432
433
434
435
class AccessList(CamelModel, RLPSerializable):
    """Access List for transactions."""

    address: Address
    storage_keys: List[Hash]

    rlp_fields: ClassVar[List[str]] = ["address", "storage_keys"]

Account

Bases: CamelModel

State associated with an address.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
class Account(CamelModel):
    """State associated with an address."""

    nonce: ZeroPaddedHexNumber = ZeroPaddedHexNumber(0)
    """
    The scalar value equal to a) the number of transactions sent by an
    Externally Owned Account, b) the amount of contracts created by a contract.
    """
    balance: ZeroPaddedHexNumber = ZeroPaddedHexNumber(0)
    """The amount of Wei (10<sup>-18</sup> Eth) the account has."""
    code: Bytes = Bytes(b"")
    """Bytecode contained by the account."""
    storage: Storage = Field(default_factory=Storage)
    """Storage within a contract."""

    model_config = {
        **CamelModel.model_config,
        "frozen": True,
    }

    @model_validator(mode="after")
    def _freeze_storage(self) -> Self:
        """
        Freeze the storage along with the account, so that accounts shared
        between allocations cannot change under any of them.
        """
        self.storage.freeze()
        return self

nonce = ZeroPaddedHexNumber(0) class-attribute instance-attribute

The scalar value equal to a) the number of transactions sent by an Externally Owned Account, b) the amount of contracts created by a contract.

balance = ZeroPaddedHexNumber(0) class-attribute instance-attribute

The amount of Wei (10-18 Eth) the account has.

code = Bytes(b'') class-attribute instance-attribute

Bytecode contained by the account.

storage = Field(default_factory=Storage) class-attribute instance-attribute

Storage within a contract.

Alloc

Bases: EthereumTestRootModel[Dict[Address, Account | None]]

Allocation of accounts in the state, pre and post test execution.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
405
406
407
408
409
410
411
412
413
414
415
416
417
class Alloc(EthereumTestRootModel[Dict[Address, Account | None]]):
    """Allocation of accounts in the state, pre and post test execution."""

    root: Dict[Address, Account | None] = Field(
        default_factory=dict, validate_default=True
    )

    def get(self, address: Address) -> Account | None:
        """Get an account if it's present in the allocation, otherwise None."""
        account = self.root.get(address)
        if not account:
            return None
        return account

get(address)

Get an account if it's present in the allocation, otherwise None.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
412
413
414
415
416
417
def get(self, address: Address) -> Account | None:
    """Get an account if it's present in the allocation, otherwise None."""
    account = self.root.get(address)
    if not account:
        return None
    return account

BlobSchedule

Bases: EthereumTestRootModel[Dict[str, ForkBlobSchedule]]

Blob schedule configuration dictionary.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
class BlobSchedule(EthereumTestRootModel[Dict[str, ForkBlobSchedule]]):
    """Blob schedule configuration dictionary."""

    root: Dict[str, ForkBlobSchedule] = Field(
        default_factory=dict, validate_default=True
    )

    def append(self, *, fork: str, schedule: Any) -> None:
        """Append a new fork schedule."""
        if not isinstance(schedule, ForkBlobSchedule):
            schedule = ForkBlobSchedule(**schedule)
        self.root[fork] = schedule

    def last(self) -> ForkBlobSchedule | None:
        """Return the last schedule."""
        if len(self.root) == 0:
            return None
        return list(self.root.values())[-1]

    def __getitem__(self, key: str) -> ForkBlobSchedule:
        """Return the schedule for a given fork."""
        return self.root[key]

append(*, fork, schedule)

Append a new fork schedule.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
453
454
455
456
457
def append(self, *, fork: str, schedule: Any) -> None:
    """Append a new fork schedule."""
    if not isinstance(schedule, ForkBlobSchedule):
        schedule = ForkBlobSchedule(**schedule)
    self.root[fork] = schedule

last()

Return the last schedule.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
459
460
461
462
463
def last(self) -> ForkBlobSchedule | None:
    """Return the last schedule."""
    if len(self.root) == 0:
        return None
    return list(self.root.values())[-1]

__getitem__(key)

Return the schedule for a given fork.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
465
466
467
def __getitem__(self, key: str) -> ForkBlobSchedule:
    """Return the schedule for a given fork."""
    return self.root[key]

ForkBlobSchedule

Bases: CamelModel

Representation of the blob schedule of a given fork.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
438
439
440
441
442
443
class ForkBlobSchedule(CamelModel):
    """Representation of the blob schedule of a given fork."""

    target_blobs_per_block: HexNumber = Field(..., alias="target")
    max_blobs_per_block: HexNumber = Field(..., alias="max")
    base_fee_update_fraction: HexNumber = Field(...)

StateCommitment

Bases: Enum

The state-commitment scheme used to compute an allocation's state root.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
420
421
422
423
424
425
426
class StateCommitment(Enum):
    """
    The state-commitment scheme used to compute an allocation's state root.
    """

    MPT = auto()
    """Merkle-Patricia trie."""

MPT = auto() class-attribute instance-attribute

Merkle-Patricia trie.

Storage

Bases: EthereumTestRootModel[Dict[StorageKeyValueType, StorageKeyValueType]]

Definition of contract storage in the pre or post state of a test.

This model accepts a dictionary with keys and values as any of: str, int, bytes, or any type that supports conversion to bytes, and automatically casts them to HashInt.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
class Storage(
    EthereumTestRootModel[Dict[StorageKeyValueType, StorageKeyValueType]]
):
    """
    Definition of contract storage in the `pre` or `post` state of a test.

    This model accepts a dictionary with keys and values as any of: str, int,
    bytes, or any type that supports conversion to bytes, and automatically
    casts them to `HashInt`.
    """

    # internal storage is maintained as a dict with HashInt keys and values.
    root: Dict[StorageKeyValueType, StorageKeyValueType] = Field(
        default_factory=dict
    )

    _current_slot: int = PrivateAttr(0)
    _hint_map: Dict[StorageKeyValueType, str] = PrivateAttr(
        default_factory=dict
    )
    _any_map: Dict[StorageKeyValueType, bool] = PrivateAttr(
        default_factory=dict
    )
    _frozen: bool = PrivateAttr(False)
    """
    Set once the storage belongs to an `Account`, which may be shared
    between allocations, so that no write can reach the others.
    """

    StorageDictType: ClassVar[TypeAlias] = Dict[
        str | int | bytes | SupportsBytes, str | int | bytes | SupportsBytes
    ]
    """
    Dictionary type to be used when defining an input to initialize a storage.
    """

    @dataclass(kw_only=True)
    class InvalidTypeError(Exception):
        """
        Invalid type used when describing test's expected storage key or value.
        """

        key_or_value: Any

        def __init__(self, key_or_value: Any, *args: Any) -> None:
            """Initialize the exception with the invalid type."""
            super().__init__(args)
            self.key_or_value = key_or_value

        def __str__(self) -> str:
            """Print exception string."""
            return f"invalid type for key/value: {self.key_or_value}"

    @dataclass(kw_only=True)
    class InvalidValueError(Exception):
        """
        Invalid value used when describing test's expected storage key or
        value.
        """

        key_or_value: Any

        def __init__(self, key_or_value: Any, *args: Any) -> None:
            """Initialize the exception with the invalid value."""
            super().__init__(args)
            self.key_or_value = key_or_value

        def __str__(self) -> str:
            """Print exception string."""
            return f"invalid value for key/value: {self.key_or_value}"

    @dataclass(kw_only=True)
    class MissingKeyError(Exception):
        """Test expected to find a storage key set but key was missing."""

        key: int

        def __init__(self, key: int, *args: Any) -> None:
            """Initialize the exception with the missing key."""
            super().__init__(args)
            self.key = key

        def __str__(self) -> str:
            """Print exception string."""
            return "key {0} not found in storage".format(Hash(self.key))

    @dataclass(kw_only=True)
    class KeyValueMismatchError(Exception):
        """
        Test expected a certain value in a storage key but value found was
        different.
        """

        address: Address
        key: int
        want: int
        got: int
        hint: str

        def __init__(
            self,
            address: Address,
            key: int,
            want: int,
            got: int,
            hint: str = "",
            *args: Any,
        ) -> None:
            """
            Initialize the exception with the address, key, wanted and got
            values.
            """
            super().__init__(args)
            self.address = address
            self.key = key
            self.want = want
            self.got = got
            self.hint = hint

        def __str__(self) -> str:
            """Print exception string."""
            label_str = ""
            if self.address.label is not None:
                label_str = f" ({self.address.label})"
            hint_str = f" ({self.hint})" if self.hint else ""
            return (
                f"incorrect value in address {self.address}{label_str} for "
                + f"key {Hash(self.key)}{hint_str}:"
                + f" want {HexNumber(self.want)} (dec:{int(self.want)}),"
                + f" got {HexNumber(self.got)} (dec:{int(self.got)})"
            )

    def __contains__(
        self, key: StorageKeyValueTypeConvertible | StorageKeyValueType
    ) -> bool:
        """Check for an item in the storage."""
        return StorageKeyValueTypeAdapter.validate_python(key) in self.root

    def __getitem__(
        self, key: StorageKeyValueTypeConvertible | StorageKeyValueType
    ) -> StorageKeyValueType:
        """Return an item from the storage."""
        return self.root[StorageKeyValueTypeAdapter.validate_python(key)]

    def freeze(self) -> "Storage":
        """Reject any further writes to the storage, and return it."""
        self._frozen = True
        return self

    def _require_mutable(self) -> None:
        """Raise if the storage is frozen."""
        if self._frozen:
            raise TypeError(
                "Storage is frozen: it belongs to an Account, which may be "
                "shared between allocations. Build the storage before "
                "creating the Account, or replace the account with "
                "`model_copy(update={'storage': ...})`."
            )

    def __setitem__(
        self,
        key: StorageKeyValueTypeConvertible | StorageKeyValueType,
        value: StorageKeyValueTypeConvertible | StorageKeyValueType,
    ) -> None:
        """Set an item in the storage."""
        self._require_mutable()
        self.root[StorageKeyValueTypeAdapter.validate_python(key)] = (
            StorageKeyValueTypeAdapter.validate_python(value)
        )

    def __delitem__(
        self, key: StorageKeyValueTypeConvertible | StorageKeyValueType
    ) -> None:
        """Delete an item from the storage."""
        self._require_mutable()
        del self.root[StorageKeyValueTypeAdapter.validate_python(key)]

    def __iter__(self) -> Iterator[StorageKeyValueType]:  # type: ignore [override]
        """Return an iterator over the storage."""
        return iter(self.root)

    def __eq__(self, other: object) -> bool:
        """Return True if both storages are equal."""
        if not isinstance(other, Storage):
            return False
        return self.root == other.root

    def __ne__(self, other: object) -> bool:
        """Return True if both storages are not equal."""
        if not isinstance(other, Storage):
            return False
        return self.root != other.root

    def __bool__(self) -> bool:
        """Return True if the storage is not empty."""
        return any(v for v in self.root.values())

    def __add__(self, other: "Storage") -> "Storage":
        """Return a new storage that is the sum of two storages."""
        return Storage({**self.root, **other.root})

    def __len__(self) -> int:
        """
        Return the number of keys that have been explicitly set in the storage.
        """
        return len(self.root)

    def keys(self) -> set[StorageKeyValueType]:
        """Return the keys of the storage."""
        return set(self.root.keys())

    def set_next_slot(self, slot: int) -> "Storage":
        """Set the next slot to be used by `store_next`."""
        self._require_mutable()
        self._current_slot = slot
        return self

    def items(self) -> ItemsView[StorageKeyValueType, StorageKeyValueType]:
        """Return the items of the storage."""
        return self.root.items()

    def set_expect_any(
        self, key: StorageKeyValueTypeConvertible | StorageKeyValueType
    ) -> None:
        """
        Mark key to be able to have any expected value when comparing storages.
        """
        self._require_mutable()
        self._any_map[StorageKeyValueTypeAdapter.validate_python(key)] = True

    def store_next(
        self,
        value: StorageKeyValueTypeConvertible | StorageKeyValueType | bool,
        hint: str = "",
    ) -> StorageKeyValueType:
        """
        Store a value in the storage and return the key where the value is
        stored.

        Increments the key counter so the next time this function is called,
        the next key is used.
        """
        self._require_mutable()
        slot = StorageKeyValueTypeAdapter.validate_python(self._current_slot)
        self._current_slot += 1
        if hint:
            self._hint_map[slot] = hint
        self[slot] = StorageKeyValueTypeAdapter.validate_python(value)
        return slot

    def peek_slot(self) -> int:
        """Peek the next slot that will be used by `store_next`."""
        return self._current_slot

    def contains(self, other: "Storage") -> bool:
        """
        Return True if self contains all keys with equal value as contained by
        second storage. Used for comparison with test expected post state and
        alloc returned by the transition tool.
        """
        for key in other.keys():
            if key not in self:
                return False
            if self[key] != other[key]:
                return False
        return True

    def must_contain(self, address: Address, other: "Storage") -> None:
        """
        Succeeds only if self contains all keys with equal value as contained
        by second storage. Used for comparison with test expected post state
        and alloc returned by the transition tool. Raises detailed exception
        when a difference is found.
        """
        for key in other.keys():
            if key not in self:
                # storage[key]==0 is equal to missing storage
                if other[key] != 0:
                    raise Storage.MissingKeyError(key=key)
            elif self[key] != other[key]:
                raise Storage.KeyValueMismatchError(
                    address=address,
                    key=key,
                    want=self[key],
                    got=other[key],
                    hint=self._hint_map.get(key, ""),
                )

    def must_be_equal(self, address: Address, other: "Storage | None") -> None:
        """Succeed only if "self" is equal to "other" storage."""
        # Test keys contained in both storage objects
        if other is None:
            other = Storage({})
        for key in self.keys() & other.keys():
            if self[key] != other[key]:
                raise Storage.KeyValueMismatchError(
                    address=address,
                    key=key,
                    want=self[key],
                    got=other[key],
                    hint=self._hint_map.get(key, ""),
                )

        # Test keys contained in either one of the storage objects
        for key in self.keys() ^ other.keys():
            if key in self:
                if self[key] != 0:
                    raise Storage.KeyValueMismatchError(
                        address=address,
                        key=key,
                        want=self[key],
                        got=0,
                        hint=self._hint_map.get(key, ""),
                    )

            elif other[key] != 0:
                # Skip key verification if we allow this key to be ANY
                if self._any_map.get(key) is True:
                    continue
                raise Storage.KeyValueMismatchError(
                    address=address,
                    key=key,
                    want=0,
                    got=other[key],
                    hint=self._hint_map.get(key, ""),
                )

    def canary(self) -> "Storage":
        """
        Return a canary storage filled with non-zero values where the current
        storage expects zero values, to guarantee that the test overwrites the
        storage.
        """
        return Storage(
            {key: HashInt(0xBA5E) for key in self.keys() if self[key] == 0}
        )

StorageDictType = Dict[str | int | bytes | SupportsBytes, str | int | bytes | SupportsBytes] class-attribute

Dictionary type to be used when defining an input to initialize a storage.

InvalidTypeError dataclass

Bases: Exception

Invalid type used when describing test's expected storage key or value.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
@dataclass(kw_only=True)
class InvalidTypeError(Exception):
    """
    Invalid type used when describing test's expected storage key or value.
    """

    key_or_value: Any

    def __init__(self, key_or_value: Any, *args: Any) -> None:
        """Initialize the exception with the invalid type."""
        super().__init__(args)
        self.key_or_value = key_or_value

    def __str__(self) -> str:
        """Print exception string."""
        return f"invalid type for key/value: {self.key_or_value}"

__init__(key_or_value, *args)

Initialize the exception with the invalid type.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
81
82
83
84
def __init__(self, key_or_value: Any, *args: Any) -> None:
    """Initialize the exception with the invalid type."""
    super().__init__(args)
    self.key_or_value = key_or_value

__str__()

Print exception string.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
86
87
88
def __str__(self) -> str:
    """Print exception string."""
    return f"invalid type for key/value: {self.key_or_value}"

InvalidValueError dataclass

Bases: Exception

Invalid value used when describing test's expected storage key or value.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
@dataclass(kw_only=True)
class InvalidValueError(Exception):
    """
    Invalid value used when describing test's expected storage key or
    value.
    """

    key_or_value: Any

    def __init__(self, key_or_value: Any, *args: Any) -> None:
        """Initialize the exception with the invalid value."""
        super().__init__(args)
        self.key_or_value = key_or_value

    def __str__(self) -> str:
        """Print exception string."""
        return f"invalid value for key/value: {self.key_or_value}"

__init__(key_or_value, *args)

Initialize the exception with the invalid value.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
 99
100
101
102
def __init__(self, key_or_value: Any, *args: Any) -> None:
    """Initialize the exception with the invalid value."""
    super().__init__(args)
    self.key_or_value = key_or_value

__str__()

Print exception string.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
104
105
106
def __str__(self) -> str:
    """Print exception string."""
    return f"invalid value for key/value: {self.key_or_value}"

MissingKeyError dataclass

Bases: Exception

Test expected to find a storage key set but key was missing.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
108
109
110
111
112
113
114
115
116
117
118
119
120
121
@dataclass(kw_only=True)
class MissingKeyError(Exception):
    """Test expected to find a storage key set but key was missing."""

    key: int

    def __init__(self, key: int, *args: Any) -> None:
        """Initialize the exception with the missing key."""
        super().__init__(args)
        self.key = key

    def __str__(self) -> str:
        """Print exception string."""
        return "key {0} not found in storage".format(Hash(self.key))

__init__(key, *args)

Initialize the exception with the missing key.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
114
115
116
117
def __init__(self, key: int, *args: Any) -> None:
    """Initialize the exception with the missing key."""
    super().__init__(args)
    self.key = key

__str__()

Print exception string.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
119
120
121
def __str__(self) -> str:
    """Print exception string."""
    return "key {0} not found in storage".format(Hash(self.key))

KeyValueMismatchError dataclass

Bases: Exception

Test expected a certain value in a storage key but value found was different.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
@dataclass(kw_only=True)
class KeyValueMismatchError(Exception):
    """
    Test expected a certain value in a storage key but value found was
    different.
    """

    address: Address
    key: int
    want: int
    got: int
    hint: str

    def __init__(
        self,
        address: Address,
        key: int,
        want: int,
        got: int,
        hint: str = "",
        *args: Any,
    ) -> None:
        """
        Initialize the exception with the address, key, wanted and got
        values.
        """
        super().__init__(args)
        self.address = address
        self.key = key
        self.want = want
        self.got = got
        self.hint = hint

    def __str__(self) -> str:
        """Print exception string."""
        label_str = ""
        if self.address.label is not None:
            label_str = f" ({self.address.label})"
        hint_str = f" ({self.hint})" if self.hint else ""
        return (
            f"incorrect value in address {self.address}{label_str} for "
            + f"key {Hash(self.key)}{hint_str}:"
            + f" want {HexNumber(self.want)} (dec:{int(self.want)}),"
            + f" got {HexNumber(self.got)} (dec:{int(self.got)})"
        )

__init__(address, key, want, got, hint='', *args)

Initialize the exception with the address, key, wanted and got values.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
def __init__(
    self,
    address: Address,
    key: int,
    want: int,
    got: int,
    hint: str = "",
    *args: Any,
) -> None:
    """
    Initialize the exception with the address, key, wanted and got
    values.
    """
    super().__init__(args)
    self.address = address
    self.key = key
    self.want = want
    self.got = got
    self.hint = hint

__str__()

Print exception string.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
156
157
158
159
160
161
162
163
164
165
166
167
def __str__(self) -> str:
    """Print exception string."""
    label_str = ""
    if self.address.label is not None:
        label_str = f" ({self.address.label})"
    hint_str = f" ({self.hint})" if self.hint else ""
    return (
        f"incorrect value in address {self.address}{label_str} for "
        + f"key {Hash(self.key)}{hint_str}:"
        + f" want {HexNumber(self.want)} (dec:{int(self.want)}),"
        + f" got {HexNumber(self.got)} (dec:{int(self.got)})"
    )

__contains__(key)

Check for an item in the storage.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
169
170
171
172
173
def __contains__(
    self, key: StorageKeyValueTypeConvertible | StorageKeyValueType
) -> bool:
    """Check for an item in the storage."""
    return StorageKeyValueTypeAdapter.validate_python(key) in self.root

__getitem__(key)

Return an item from the storage.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
175
176
177
178
179
def __getitem__(
    self, key: StorageKeyValueTypeConvertible | StorageKeyValueType
) -> StorageKeyValueType:
    """Return an item from the storage."""
    return self.root[StorageKeyValueTypeAdapter.validate_python(key)]

freeze()

Reject any further writes to the storage, and return it.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
181
182
183
184
def freeze(self) -> "Storage":
    """Reject any further writes to the storage, and return it."""
    self._frozen = True
    return self

__setitem__(key, value)

Set an item in the storage.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
196
197
198
199
200
201
202
203
204
205
def __setitem__(
    self,
    key: StorageKeyValueTypeConvertible | StorageKeyValueType,
    value: StorageKeyValueTypeConvertible | StorageKeyValueType,
) -> None:
    """Set an item in the storage."""
    self._require_mutable()
    self.root[StorageKeyValueTypeAdapter.validate_python(key)] = (
        StorageKeyValueTypeAdapter.validate_python(value)
    )

__delitem__(key)

Delete an item from the storage.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
207
208
209
210
211
212
def __delitem__(
    self, key: StorageKeyValueTypeConvertible | StorageKeyValueType
) -> None:
    """Delete an item from the storage."""
    self._require_mutable()
    del self.root[StorageKeyValueTypeAdapter.validate_python(key)]

__iter__()

Return an iterator over the storage.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
214
215
216
def __iter__(self) -> Iterator[StorageKeyValueType]:  # type: ignore [override]
    """Return an iterator over the storage."""
    return iter(self.root)

__eq__(other)

Return True if both storages are equal.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
218
219
220
221
222
def __eq__(self, other: object) -> bool:
    """Return True if both storages are equal."""
    if not isinstance(other, Storage):
        return False
    return self.root == other.root

__ne__(other)

Return True if both storages are not equal.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
224
225
226
227
228
def __ne__(self, other: object) -> bool:
    """Return True if both storages are not equal."""
    if not isinstance(other, Storage):
        return False
    return self.root != other.root

__bool__()

Return True if the storage is not empty.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
230
231
232
def __bool__(self) -> bool:
    """Return True if the storage is not empty."""
    return any(v for v in self.root.values())

__add__(other)

Return a new storage that is the sum of two storages.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
234
235
236
def __add__(self, other: "Storage") -> "Storage":
    """Return a new storage that is the sum of two storages."""
    return Storage({**self.root, **other.root})

__len__()

Return the number of keys that have been explicitly set in the storage.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
238
239
240
241
242
def __len__(self) -> int:
    """
    Return the number of keys that have been explicitly set in the storage.
    """
    return len(self.root)

keys()

Return the keys of the storage.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
244
245
246
def keys(self) -> set[StorageKeyValueType]:
    """Return the keys of the storage."""
    return set(self.root.keys())

set_next_slot(slot)

Set the next slot to be used by store_next.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
248
249
250
251
252
def set_next_slot(self, slot: int) -> "Storage":
    """Set the next slot to be used by `store_next`."""
    self._require_mutable()
    self._current_slot = slot
    return self

items()

Return the items of the storage.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
254
255
256
def items(self) -> ItemsView[StorageKeyValueType, StorageKeyValueType]:
    """Return the items of the storage."""
    return self.root.items()

set_expect_any(key)

Mark key to be able to have any expected value when comparing storages.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
258
259
260
261
262
263
264
265
def set_expect_any(
    self, key: StorageKeyValueTypeConvertible | StorageKeyValueType
) -> None:
    """
    Mark key to be able to have any expected value when comparing storages.
    """
    self._require_mutable()
    self._any_map[StorageKeyValueTypeAdapter.validate_python(key)] = True

store_next(value, hint='')

Store a value in the storage and return the key where the value is stored.

Increments the key counter so the next time this function is called, the next key is used.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
def store_next(
    self,
    value: StorageKeyValueTypeConvertible | StorageKeyValueType | bool,
    hint: str = "",
) -> StorageKeyValueType:
    """
    Store a value in the storage and return the key where the value is
    stored.

    Increments the key counter so the next time this function is called,
    the next key is used.
    """
    self._require_mutable()
    slot = StorageKeyValueTypeAdapter.validate_python(self._current_slot)
    self._current_slot += 1
    if hint:
        self._hint_map[slot] = hint
    self[slot] = StorageKeyValueTypeAdapter.validate_python(value)
    return slot

peek_slot()

Peek the next slot that will be used by store_next.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
287
288
289
def peek_slot(self) -> int:
    """Peek the next slot that will be used by `store_next`."""
    return self._current_slot

contains(other)

Return True if self contains all keys with equal value as contained by second storage. Used for comparison with test expected post state and alloc returned by the transition tool.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
291
292
293
294
295
296
297
298
299
300
301
302
def contains(self, other: "Storage") -> bool:
    """
    Return True if self contains all keys with equal value as contained by
    second storage. Used for comparison with test expected post state and
    alloc returned by the transition tool.
    """
    for key in other.keys():
        if key not in self:
            return False
        if self[key] != other[key]:
            return False
    return True

must_contain(address, other)

Succeeds only if self contains all keys with equal value as contained by second storage. Used for comparison with test expected post state and alloc returned by the transition tool. Raises detailed exception when a difference is found.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
def must_contain(self, address: Address, other: "Storage") -> None:
    """
    Succeeds only if self contains all keys with equal value as contained
    by second storage. Used for comparison with test expected post state
    and alloc returned by the transition tool. Raises detailed exception
    when a difference is found.
    """
    for key in other.keys():
        if key not in self:
            # storage[key]==0 is equal to missing storage
            if other[key] != 0:
                raise Storage.MissingKeyError(key=key)
        elif self[key] != other[key]:
            raise Storage.KeyValueMismatchError(
                address=address,
                key=key,
                want=self[key],
                got=other[key],
                hint=self._hint_map.get(key, ""),
            )

must_be_equal(address, other)

Succeed only if "self" is equal to "other" storage.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
def must_be_equal(self, address: Address, other: "Storage | None") -> None:
    """Succeed only if "self" is equal to "other" storage."""
    # Test keys contained in both storage objects
    if other is None:
        other = Storage({})
    for key in self.keys() & other.keys():
        if self[key] != other[key]:
            raise Storage.KeyValueMismatchError(
                address=address,
                key=key,
                want=self[key],
                got=other[key],
                hint=self._hint_map.get(key, ""),
            )

    # Test keys contained in either one of the storage objects
    for key in self.keys() ^ other.keys():
        if key in self:
            if self[key] != 0:
                raise Storage.KeyValueMismatchError(
                    address=address,
                    key=key,
                    want=self[key],
                    got=0,
                    hint=self._hint_map.get(key, ""),
                )

        elif other[key] != 0:
            # Skip key verification if we allow this key to be ANY
            if self._any_map.get(key) is True:
                continue
            raise Storage.KeyValueMismatchError(
                address=address,
                key=key,
                want=0,
                got=other[key],
                hint=self._hint_map.get(key, ""),
            )

canary()

Return a canary storage filled with non-zero values where the current storage expects zero values, to guarantee that the test overwrites the storage.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
364
365
366
367
368
369
370
371
372
def canary(self) -> "Storage":
    """
    Return a canary storage filled with non-zero values where the current
    storage expects zero values, to guarantee that the test overwrites the
    storage.
    """
    return Storage(
        {key: HashInt(0xBA5E) for key in self.keys() if self[key] == 0}
    )

to_bytes(input_bytes)

Convert multiple types into bytes.

Source code in packages/testing/src/execution_testing/base_types/conversions.py
12
13
14
15
16
17
18
19
20
21
22
23
24
25
def to_bytes(input_bytes: BytesConvertible) -> bytes:
    """Convert multiple types into bytes."""
    if input_bytes is None:
        raise ValueError("Cannot convert `None` input to bytes")

    if isinstance(input_bytes, str):
        # We can have a hex representation of bytes with spaces for readability
        if input_bytes.startswith("0x"):
            input_bytes = input_bytes[2:]
        if len(input_bytes) % 2 == 1:
            input_bytes = "0" + input_bytes
        return bytes.fromhex(input_bytes)

    return bytes(input_bytes)

to_hex(input_bytes)

Convert multiple types into a bytes hex string.

Source code in packages/testing/src/execution_testing/base_types/conversions.py
72
73
74
def to_hex(input_bytes: BytesConvertible) -> str:
    """Convert multiple types into a bytes hex string."""
    return "0x" + to_bytes(input_bytes).hex()

CamelModel

Bases: CopyValidateModel

A base model that converts field names to camel case when serializing.

For example, the field name current_timestamp in a Python model will be represented as currentTimestamp when it is serialized to json.

Source code in packages/testing/src/execution_testing/base_types/pydantic.py
45
46
47
48
49
50
51
52
53
54
55
56
57
58
class CamelModel(CopyValidateModel):
    """
    A base model that converts field names to camel case when serializing.

    For example, the field name `current_timestamp` in a Python model will be
    represented as `currentTimestamp` when it is serialized to json.
    """

    model_config = ConfigDict(
        alias_generator=to_camel,
        populate_by_name=True,
        validate_default=True,
        extra="forbid",
    )

EthereumTestBaseModel

Bases: BaseModel, ModelCustomizationsMixin

Base model for all models for Ethereum tests.

Source code in packages/testing/src/execution_testing/base_types/pydantic.py
14
15
16
17
class EthereumTestBaseModel(BaseModel, ModelCustomizationsMixin):
    """Base model for all models for Ethereum tests."""

    pass

EthereumTestRootModel

Bases: RootModel[RootModelRootType], ModelCustomizationsMixin

Base model for all models for Ethereum tests.

Source code in packages/testing/src/execution_testing/base_types/pydantic.py
20
21
22
23
24
25
class EthereumTestRootModel(
    RootModel[RootModelRootType], ModelCustomizationsMixin
):
    """Base model for all models for Ethereum tests."""

    root: Any

ReferenceSpec

Reference Specification Description Abstract Class.

Source code in packages/testing/src/execution_testing/base_types/reference_spec/reference_spec.py
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
class ReferenceSpec:
    """Reference Specification Description Abstract Class."""

    @abstractmethod
    def name(self) -> str:
        """Return the name of the spec."""
        pass

    @abstractmethod
    def has_known_version(self) -> bool:
        """
        Return true if the reference spec object is hard-coded with a latest
        known version.
        """
        pass

    @abstractmethod
    def known_version(self) -> str:
        """Return the latest known version in the reference."""
        pass

    @abstractmethod
    def api_url(self) -> str:
        """
        Return the URL required to poll the version from an API, if needed.
        """
        pass

    @abstractmethod
    def latest_version(self) -> str:
        """Return a digest that points to the latest version of the spec."""
        pass

    @abstractmethod
    def is_outdated(self) -> bool:
        """
        Check whether the reference specification has been updated since the
        test was last updated.
        """
        pass

    @abstractmethod
    def write_info(self, info: Dict[str, Dict[str, Any] | str]) -> None:
        """
        Write info about the reference specification used into the output
        fixture.
        """
        pass

    @staticmethod
    @abstractmethod
    def parseable_from_module(module_dict: Dict[str, Any]) -> bool:
        """
        Check whether the module's dict contains required reference spec
        information.
        """
        pass

    @staticmethod
    @abstractmethod
    def parse_from_module(
        module_dict: Dict[str, Any], github_token: Optional[str] = None
    ) -> "ReferenceSpec":
        """
        Parse the module's dict into a reference spec.

        Args:
            module_dict: Dictionary containing module information
            github_token: Optional GitHub token for API authentication

        """
        pass

name() abstractmethod

Return the name of the spec.

Source code in packages/testing/src/execution_testing/base_types/reference_spec/reference_spec.py
32
33
34
35
@abstractmethod
def name(self) -> str:
    """Return the name of the spec."""
    pass

has_known_version() abstractmethod

Return true if the reference spec object is hard-coded with a latest known version.

Source code in packages/testing/src/execution_testing/base_types/reference_spec/reference_spec.py
37
38
39
40
41
42
43
@abstractmethod
def has_known_version(self) -> bool:
    """
    Return true if the reference spec object is hard-coded with a latest
    known version.
    """
    pass

known_version() abstractmethod

Return the latest known version in the reference.

Source code in packages/testing/src/execution_testing/base_types/reference_spec/reference_spec.py
45
46
47
48
@abstractmethod
def known_version(self) -> str:
    """Return the latest known version in the reference."""
    pass

api_url() abstractmethod

Return the URL required to poll the version from an API, if needed.

Source code in packages/testing/src/execution_testing/base_types/reference_spec/reference_spec.py
50
51
52
53
54
55
@abstractmethod
def api_url(self) -> str:
    """
    Return the URL required to poll the version from an API, if needed.
    """
    pass

latest_version() abstractmethod

Return a digest that points to the latest version of the spec.

Source code in packages/testing/src/execution_testing/base_types/reference_spec/reference_spec.py
57
58
59
60
@abstractmethod
def latest_version(self) -> str:
    """Return a digest that points to the latest version of the spec."""
    pass

is_outdated() abstractmethod

Check whether the reference specification has been updated since the test was last updated.

Source code in packages/testing/src/execution_testing/base_types/reference_spec/reference_spec.py
62
63
64
65
66
67
68
@abstractmethod
def is_outdated(self) -> bool:
    """
    Check whether the reference specification has been updated since the
    test was last updated.
    """
    pass

write_info(info) abstractmethod

Write info about the reference specification used into the output fixture.

Source code in packages/testing/src/execution_testing/base_types/reference_spec/reference_spec.py
70
71
72
73
74
75
76
@abstractmethod
def write_info(self, info: Dict[str, Dict[str, Any] | str]) -> None:
    """
    Write info about the reference specification used into the output
    fixture.
    """
    pass

parseable_from_module(module_dict) abstractmethod staticmethod

Check whether the module's dict contains required reference spec information.

Source code in packages/testing/src/execution_testing/base_types/reference_spec/reference_spec.py
78
79
80
81
82
83
84
85
@staticmethod
@abstractmethod
def parseable_from_module(module_dict: Dict[str, Any]) -> bool:
    """
    Check whether the module's dict contains required reference spec
    information.
    """
    pass

parse_from_module(module_dict, github_token=None) abstractmethod staticmethod

Parse the module's dict into a reference spec.

Parameters:

Name Type Description Default
module_dict Dict[str, Any]

Dictionary containing module information

required
github_token Optional[str]

Optional GitHub token for API authentication

None
Source code in packages/testing/src/execution_testing/base_types/reference_spec/reference_spec.py
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
@staticmethod
@abstractmethod
def parse_from_module(
    module_dict: Dict[str, Any], github_token: Optional[str] = None
) -> "ReferenceSpec":
    """
    Parse the module's dict into a reference spec.

    Args:
        module_dict: Dictionary containing module information
        github_token: Optional GitHub token for API authentication

    """
    pass

KnownEncodedSize

Stand in for an item whose encoded size is already known.

Source code in packages/testing/src/execution_testing/base_types/serialization.py
31
32
33
34
35
36
37
38
class KnownEncodedSize:
    """Stand in for an item whose encoded size is already known."""

    __slots__ = ("size",)

    def __init__(self, size: int) -> None:
        """Record the encoded size of the item this stands in for."""
        self.size = size

__init__(size)

Record the encoded size of the item this stands in for.

Source code in packages/testing/src/execution_testing/base_types/serialization.py
36
37
38
def __init__(self, size: int) -> None:
    """Record the encoded size of the item this stands in for."""
    self.size = size

RLPSerializable

Class that adds RLP serialization to another class.

Source code in packages/testing/src/execution_testing/base_types/serialization.py
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
class RLPSerializable:
    """Class that adds RLP serialization to another class."""

    rlp_override: Bytes | None = None

    signable: ClassVar[bool] = False
    rlp_fields: ClassVar[List[str]]
    rlp_signing_fields: ClassVar[List[str]]
    rlp_exclude_none: ClassVar[bool] = False

    def get_rlp_fields(self) -> List[str]:
        """
        Return an ordered list of field names to be included in RLP
        serialization.

        Function can be overridden to customize the logic to return the fields.

        By default, rlp_fields class variable is used.

        The list can be nested list up to one extra level to represent nested
        fields.
        """
        return self.rlp_fields

    def get_rlp_signing_fields(self) -> List[str]:
        """
        Return an ordered list of field names to be included in the RLP
        serialization of the object signature.

        Function can be overridden to customize the logic to return the fields.

        By default, rlp_signing_fields class variable is used.

        The list can be nested list up to one extra level to represent nested
        fields.
        """
        return self.rlp_signing_fields

    def get_rlp_prefix(self) -> bytes:
        """
        Return a prefix that has to be appended to the serialized object.

        By default, an empty string is returned.
        """
        return b""

    def get_rlp_signing_prefix(self) -> bytes:
        """
        Return a prefix that has to be appended to the serialized signing
        object.

        By default, an empty string is returned.
        """
        return b""

    def sign(self) -> None:
        """Sign the current object for further serialization."""
        raise NotImplementedError(
            f'Object "{self.__class__.__name__}" cannot be signed.'
        )

    def to_list_from_fields(self, fields: List[str]) -> List[Any]:
        """
        Return an RLP serializable list that can be passed to `eth_rlp.encode`.

        Can be for signing purposes or the entire object.
        """
        values_list: List[Any] = []
        for field in fields:
            assert isinstance(field, str), (
                f'Unable to rlp serialize field "{field}" '
                f'in object type "{self.__class__.__name__}"'
            )
            assert hasattr(self, field), (
                f'Unable to rlp serialize field "{field}" '
                f'in object type "{self.__class__.__name__}"'
            )
            try:
                value = getattr(self, field)
                if self.rlp_exclude_none and value is None:
                    continue
                values_list.append(to_serializable_element(value))
            except Exception as e:
                raise Exception(
                    f'Unable to rlp serialize field "{field}" '
                    f'in object type "{self.__class__.__name__}"'
                ) from e
        return values_list

    def to_list(self, signing: bool = False) -> List[Any]:
        """
        Return an RLP serializable list that can be passed to `eth_rlp.encode`.

        Can be for signing purposes or the entire object.
        """
        field_list: List[str]
        if signing:
            if not self.signable:
                raise Exception(
                    f'Object "{self.__class__.__name__}" '
                    "does not support signing"
                )
            field_list = self.get_rlp_signing_fields()
        else:
            if self.signable:
                # Automatically sign signable objects during full
                # serialization: Ensures nested objects have valid signatures
                # in the final RLP.
                self.sign()
            field_list = self.get_rlp_fields()

        return self.to_list_from_fields(field_list)

    def rlp_signing_bytes(self) -> Bytes:
        """Return the signing serialized envelope used for signing."""
        return Bytes(
            self.get_rlp_signing_prefix()
            + eth_rlp.encode(self.to_list(signing=True))
        )

    def rlp(self) -> Bytes:
        """Return the serialized object."""
        if self.rlp_override is not None:
            return self.rlp_override
        return Bytes(
            self.get_rlp_prefix() + eth_rlp.encode(self.to_list(signing=False))
        )

    def rlp_size(self) -> int:
        """Return `len(self.rlp())` without building the encoding."""
        if self.rlp_override is not None:
            return len(self.rlp_override)
        return len(self.get_rlp_prefix()) + encoded_size(
            self.to_list(signing=False)
        )

    @classmethod
    def list_root(cls, element_list: Sequence[Self]) -> bytes:
        """Return the root of a list of the given type."""
        t = HexaryTrie(db={})
        for i, e in enumerate(element_list):
            t.set(
                eth_rlp.encode(Uint(i)),
                e.rlp(),
            )
        return t.root_hash

get_rlp_fields()

Return an ordered list of field names to be included in RLP serialization.

Function can be overridden to customize the logic to return the fields.

By default, rlp_fields class variable is used.

The list can be nested list up to one extra level to represent nested fields.

Source code in packages/testing/src/execution_testing/base_types/serialization.py
116
117
118
119
120
121
122
123
124
125
126
127
128
def get_rlp_fields(self) -> List[str]:
    """
    Return an ordered list of field names to be included in RLP
    serialization.

    Function can be overridden to customize the logic to return the fields.

    By default, rlp_fields class variable is used.

    The list can be nested list up to one extra level to represent nested
    fields.
    """
    return self.rlp_fields

get_rlp_signing_fields()

Return an ordered list of field names to be included in the RLP serialization of the object signature.

Function can be overridden to customize the logic to return the fields.

By default, rlp_signing_fields class variable is used.

The list can be nested list up to one extra level to represent nested fields.

Source code in packages/testing/src/execution_testing/base_types/serialization.py
130
131
132
133
134
135
136
137
138
139
140
141
142
def get_rlp_signing_fields(self) -> List[str]:
    """
    Return an ordered list of field names to be included in the RLP
    serialization of the object signature.

    Function can be overridden to customize the logic to return the fields.

    By default, rlp_signing_fields class variable is used.

    The list can be nested list up to one extra level to represent nested
    fields.
    """
    return self.rlp_signing_fields

get_rlp_prefix()

Return a prefix that has to be appended to the serialized object.

By default, an empty string is returned.

Source code in packages/testing/src/execution_testing/base_types/serialization.py
144
145
146
147
148
149
150
def get_rlp_prefix(self) -> bytes:
    """
    Return a prefix that has to be appended to the serialized object.

    By default, an empty string is returned.
    """
    return b""

get_rlp_signing_prefix()

Return a prefix that has to be appended to the serialized signing object.

By default, an empty string is returned.

Source code in packages/testing/src/execution_testing/base_types/serialization.py
152
153
154
155
156
157
158
159
def get_rlp_signing_prefix(self) -> bytes:
    """
    Return a prefix that has to be appended to the serialized signing
    object.

    By default, an empty string is returned.
    """
    return b""

sign()

Sign the current object for further serialization.

Source code in packages/testing/src/execution_testing/base_types/serialization.py
161
162
163
164
165
def sign(self) -> None:
    """Sign the current object for further serialization."""
    raise NotImplementedError(
        f'Object "{self.__class__.__name__}" cannot be signed.'
    )

to_list_from_fields(fields)

Return an RLP serializable list that can be passed to eth_rlp.encode.

Can be for signing purposes or the entire object.

Source code in packages/testing/src/execution_testing/base_types/serialization.py
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
def to_list_from_fields(self, fields: List[str]) -> List[Any]:
    """
    Return an RLP serializable list that can be passed to `eth_rlp.encode`.

    Can be for signing purposes or the entire object.
    """
    values_list: List[Any] = []
    for field in fields:
        assert isinstance(field, str), (
            f'Unable to rlp serialize field "{field}" '
            f'in object type "{self.__class__.__name__}"'
        )
        assert hasattr(self, field), (
            f'Unable to rlp serialize field "{field}" '
            f'in object type "{self.__class__.__name__}"'
        )
        try:
            value = getattr(self, field)
            if self.rlp_exclude_none and value is None:
                continue
            values_list.append(to_serializable_element(value))
        except Exception as e:
            raise Exception(
                f'Unable to rlp serialize field "{field}" '
                f'in object type "{self.__class__.__name__}"'
            ) from e
    return values_list

to_list(signing=False)

Return an RLP serializable list that can be passed to eth_rlp.encode.

Can be for signing purposes or the entire object.

Source code in packages/testing/src/execution_testing/base_types/serialization.py
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
def to_list(self, signing: bool = False) -> List[Any]:
    """
    Return an RLP serializable list that can be passed to `eth_rlp.encode`.

    Can be for signing purposes or the entire object.
    """
    field_list: List[str]
    if signing:
        if not self.signable:
            raise Exception(
                f'Object "{self.__class__.__name__}" '
                "does not support signing"
            )
        field_list = self.get_rlp_signing_fields()
    else:
        if self.signable:
            # Automatically sign signable objects during full
            # serialization: Ensures nested objects have valid signatures
            # in the final RLP.
            self.sign()
        field_list = self.get_rlp_fields()

    return self.to_list_from_fields(field_list)

rlp_signing_bytes()

Return the signing serialized envelope used for signing.

Source code in packages/testing/src/execution_testing/base_types/serialization.py
219
220
221
222
223
224
def rlp_signing_bytes(self) -> Bytes:
    """Return the signing serialized envelope used for signing."""
    return Bytes(
        self.get_rlp_signing_prefix()
        + eth_rlp.encode(self.to_list(signing=True))
    )

rlp()

Return the serialized object.

Source code in packages/testing/src/execution_testing/base_types/serialization.py
226
227
228
229
230
231
232
def rlp(self) -> Bytes:
    """Return the serialized object."""
    if self.rlp_override is not None:
        return self.rlp_override
    return Bytes(
        self.get_rlp_prefix() + eth_rlp.encode(self.to_list(signing=False))
    )

rlp_size()

Return len(self.rlp()) without building the encoding.

Source code in packages/testing/src/execution_testing/base_types/serialization.py
234
235
236
237
238
239
240
def rlp_size(self) -> int:
    """Return `len(self.rlp())` without building the encoding."""
    if self.rlp_override is not None:
        return len(self.rlp_override)
    return len(self.get_rlp_prefix()) + encoded_size(
        self.to_list(signing=False)
    )

list_root(element_list) classmethod

Return the root of a list of the given type.

Source code in packages/testing/src/execution_testing/base_types/serialization.py
242
243
244
245
246
247
248
249
250
251
@classmethod
def list_root(cls, element_list: Sequence[Self]) -> bytes:
    """Return the root of a list of the given type."""
    t = HexaryTrie(db={})
    for i, e in enumerate(element_list):
        t.set(
            eth_rlp.encode(Uint(i)),
            e.rlp(),
        )
    return t.root_hash

SignableRLPSerializable

Bases: RLPSerializable

Class that adds RLP serialization to another class with signing support.

Source code in packages/testing/src/execution_testing/base_types/serialization.py
254
255
256
257
258
259
260
261
262
263
264
265
class SignableRLPSerializable(RLPSerializable):
    """
    Class that adds RLP serialization to another class with signing support.
    """

    signable: ClassVar[bool] = True

    def sign(self) -> None:
        """Sign the current object for further serialization."""
        raise NotImplementedError(
            f'Object "{self.__class__.__name__}" needs to implement `sign`.'
        )

sign()

Sign the current object for further serialization.

Source code in packages/testing/src/execution_testing/base_types/serialization.py
261
262
263
264
265
def sign(self) -> None:
    """Sign the current object for further serialization."""
    raise NotImplementedError(
        f'Object "{self.__class__.__name__}" needs to implement `sign`.'
    )

encoded_prefixed_size(payload_size)

Return the encoded size of an item with a payload of payload_size bytes, its length prefix included.

Source code in packages/testing/src/execution_testing/base_types/serialization.py
41
42
43
44
45
46
47
48
def encoded_prefixed_size(payload_size: int) -> int:
    """
    Return the encoded size of an item with a payload of `payload_size`
    bytes, its length prefix included.
    """
    if payload_size < 0x38:
        return 1 + payload_size
    return 1 + len(Uint(payload_size).to_be_bytes()) + payload_size

encoded_size(raw_data)

Return len(eth_rlp.encode(raw_data)) without building the encoding.

This covers the same cases as ethereum_rlp.encode, plus KnownEncodedSize placeholders, so measuring the size of a large structure costs a walk over it instead of megabytes of intermediate byte strings. The concrete types come first: the abstract Sequence check is slow enough to dominate the walk.

Source code in packages/testing/src/execution_testing/base_types/serialization.py
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
def encoded_size(raw_data: Any) -> int:
    """
    Return `len(eth_rlp.encode(raw_data))` without building the encoding.

    This covers the same cases as `ethereum_rlp.encode`, plus
    `KnownEncodedSize` placeholders, so measuring the size of a large
    structure costs a walk over it instead of megabytes of intermediate byte
    strings. The concrete types come first: the abstract
    `Sequence` check is slow enough to dominate the walk.
    """
    if isinstance(raw_data, (bytearray, bytes)):
        return _encoded_bytes_size(raw_data)
    elif isinstance(raw_data, (list, tuple)):
        return _encoded_sequence_size(raw_data)
    elif isinstance(raw_data, (Uint, FixedUnsigned)):
        return _encoded_unsigned_size(int(raw_data))
    elif isinstance(raw_data, KnownEncodedSize):
        return raw_data.size
    elif isinstance(raw_data, bool):
        return 1
    elif isinstance(raw_data, str):
        return _encoded_bytes_size(raw_data.encode())
    elif isinstance(raw_data, Sequence):
        return _encoded_sequence_size(raw_data)
    elif is_dataclass(raw_data) and not isinstance(raw_data, type):
        return _encoded_sequence_size(astuple(raw_data))
    else:
        raise EncodingError(
            "RLP encoded size of type {} is not supported".format(
                type(raw_data)
            )
        )

unwrap_annotation(hint)

Recursively unwrap Annotated and Union types to find the actual type.

This function is useful for introspecting complex type annotations like: - Annotated[int, ...] -> int - int | None -> int - Annotated[int, ...] | None -> int

Parameters:

Name Type Description Default
hint Any

Type annotation to unwrap

required

Returns:

Type Description
Any

The unwrapped base type

Source code in packages/testing/src/execution_testing/base_types/typing_utils.py
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
def unwrap_annotation(hint: Any) -> Any:
    """
    Recursively unwrap Annotated and Union types to find the actual type.

    This function is useful for introspecting complex type annotations like:
    - `Annotated[int, ...]` -> `int`
    - `int | None` -> `int`
    - `Annotated[int, ...] | None` -> `int`

    Args:
        hint: Type annotation to unwrap

    Returns:
        The unwrapped base type

    """
    type_args = get_args(hint)
    if not type_args:
        # Base case: simple type with no parameters
        return hint

    # For Union types (including Optional), find the first non-None type
    for arg in type_args:
        if arg is not type(None):
            # Recursively unwrap (handles nested Annotated/Union)
            return unwrap_annotation(arg)

    # All args were None (shouldn't happen in practice)
    return hint