|
4 | 4 | from pathlib import Path |
5 | 5 | from typing import Annotated, Any, Dict, List, Self |
6 | 6 |
|
7 | | -from pydantic import Field |
| 7 | +from pydantic import Field, PlainSerializer, PlainValidator |
8 | 8 |
|
9 | 9 | from ethereum_test_base_types import ( |
10 | 10 | BlobSchedule, |
|
29 | 29 | Transaction, |
30 | 30 | TransactionReceipt, |
31 | 31 | ) |
| 32 | +from ethereum_test_vm import Opcode, Opcodes |
32 | 33 | from pytest_plugins.custom_logging import get_logger |
33 | 34 |
|
34 | 35 | logger = get_logger(__name__) |
@@ -175,6 +176,40 @@ def print(self): |
175 | 176 | tx.print() |
176 | 177 |
|
177 | 178 |
|
| 179 | +_opcode_synonyms = { |
| 180 | + "KECCAK256": "SHA3", |
| 181 | +} |
| 182 | + |
| 183 | + |
| 184 | +def validate_opcode(obj: Any) -> Opcodes: |
| 185 | + """Validate an opcode from a string.""" |
| 186 | + if isinstance(obj, Opcode) or isinstance(obj, Opcodes): |
| 187 | + return obj |
| 188 | + if isinstance(obj, str): |
| 189 | + if obj in _opcode_synonyms: |
| 190 | + obj = _opcode_synonyms[obj] |
| 191 | + for op in Opcodes: |
| 192 | + if str(op) == obj: |
| 193 | + return op |
| 194 | + raise Exception(f"Unable to validate {obj} (type={type(obj)})") |
| 195 | + |
| 196 | + |
| 197 | +class OpcodeCount(EthereumTestRootModel): |
| 198 | + """Opcode count returned from the evm tool.""" |
| 199 | + |
| 200 | + root: Dict[ |
| 201 | + Annotated[Opcodes, PlainValidator(validate_opcode), PlainSerializer(lambda o: str(o))], int |
| 202 | + ] |
| 203 | + |
| 204 | + def __add__(self, other: Self) -> Self: |
| 205 | + """Add two instances of opcode count dictionaries.""" |
| 206 | + assert isinstance(other, OpcodeCount), f"Incompatible type {type(other)}" |
| 207 | + new_dict = self.model_dump() | other.model_dump() |
| 208 | + for match_key in self.root.keys() & other.root.keys(): |
| 209 | + new_dict[match_key] = self.root[match_key] + other.root[match_key] |
| 210 | + return OpcodeCount(new_dict) |
| 211 | + |
| 212 | + |
178 | 213 | class Result(CamelModel): |
179 | 214 | """Result of a transition tool output.""" |
180 | 215 |
|
@@ -202,6 +237,7 @@ class Result(CamelModel): |
202 | 237 | BlockExceptionWithMessage | UndefinedException | None, ExceptionMapperValidator |
203 | 238 | ] = None |
204 | 239 | traces: Traces | None = None |
| 240 | + opcode_count: OpcodeCount | None = None |
205 | 241 |
|
206 | 242 |
|
207 | 243 | class TransitionToolInput(CamelModel): |
|
0 commit comments