Skip to content

Commit f0cb1bd

Browse files
committed
fix(tests/static): Fine tune addr tag script, turn on more static tests for tagging.
- Wrap up stTransaction tests fine-tuning - [fine-tuning] Replace 0 address in CALL code if in pre - Changes from comments on PR ethereum#1781: - Use Prague.precompiles() for precompile addresses in convert_addresses.py - Revamp script, simplify Claude code over-engineering. - fine tune by not tagging some addrs, add short name tag compat for selected tests
1 parent 5a87a65 commit f0cb1bd

File tree

2,256 files changed

+49156
-22032
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

2,256 files changed

+49156
-22032
lines changed

convert_addresses.py

Lines changed: 0 additions & 475 deletions
This file was deleted.

failed_tests_output.txt

Lines changed: 26392 additions & 0 deletions
Large diffs are not rendered by default.

scripts/convert_addresses.py

Lines changed: 1025 additions & 0 deletions
Large diffs are not rendered by default.

src/ethereum_test_specs/static_state/common/common.py

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def parse_hex_number(i: str | int) -> int:
3232
return int(i, 10)
3333

3434

35-
def parse_value_or_address_tag(value: Any) -> Union[HexNumber, str]:
35+
def parse_value_or_address_tag(value: Union[HexNumber, str]) -> Union[HexNumber, str]:
3636
"""Parse either a hex number or an address tag for storage values."""
3737
if not isinstance(value, str):
3838
# Non-string values should be converted to HexNumber normally
@@ -121,7 +121,7 @@ def compiled(self) -> bytes:
121121
else:
122122
options.append(arg)
123123

124-
with tempfile.NamedTemporaryFile(mode="w+", delete=False) as tmp:
124+
with tempfile.NamedTemporaryFile(mode="w+", delete=False, suffix=".yul") as tmp:
125125
tmp.write(native_yul_options + self.code_raw[source_start:])
126126
tmp_path = tmp.name
127127
compiled_code = compile_yul(
@@ -205,12 +205,17 @@ def parse_code_label(code) -> CodeInFillerSource:
205205

206206

207207
class AddressTag:
208-
"""Represents an address tag like <eoa:sender> or <contract:token>."""
208+
"""
209+
Represents an address tag like:
210+
- <eoa:sender:0x...>.
211+
- <contract:target:0x...>.
212+
- <coinbase:0x...>.
213+
"""
209214

210215
def __init__(self, tag_type: str, tag_name: str, original_string: str):
211216
"""Initialize address tag."""
212-
self.tag_type = tag_type # "eoa" or "contract"
213-
self.tag_name = tag_name # e.g., "sender", "token"
217+
self.tag_type = tag_type # "eoa", "contract", or "coinbase"
218+
self.tag_name = tag_name # e.g., "sender", "target", or address for 2-part tags
214219
self.original_string = original_string
215220

216221
def __str__(self) -> str:
@@ -244,21 +249,32 @@ def parse_address_or_tag(value: Any) -> Union[Address, AddressTag]:
244249
return Address(value, left_padding=True)
245250

246251
# Check if it matches tag pattern:
247-
# - <eoa:0x...> or <contract:0x...>
248-
# - <eoa:name:0x...> or <contract:name:0x...>
249-
tag_pattern = r"^<(eoa|contract):(.+)>$"
250-
match = re.match(tag_pattern, value.strip())
252+
# - <eoa:0x...>, <contract:0x...>, <coinbase:0x...>
253+
# - <eoa:name:0x...>, <contract:name:0x...>
254+
255+
# Try 3-part pattern first (type:name:address)
256+
tag_pattern_3_part = r"^<(eoa|contract|coinbase):([^:]+):(.+)>$"
257+
match = re.match(tag_pattern_3_part, value.strip())
251258

252259
if match:
253260
tag_type = match.group(1)
254-
# The tag_name is everything after the type and colon
255-
# Could be "0x1234..." or "sender:0x1234..."
256261
tag_name = match.group(2)
257-
262+
address_part = match.group(3)
263+
# For 3-part tags, the tag_name is the middle part
258264
return AddressTag(tag_type, tag_name, value.strip())
259-
else:
260-
# Regular address string
261-
return Address(value, left_padding=True)
265+
266+
# Try 2-part pattern (type:address)
267+
tag_pattern_2_part = r"^<(eoa|contract|coinbase):(.+)>$"
268+
match = re.match(tag_pattern_2_part, value.strip())
269+
270+
if match:
271+
tag_type = match.group(1)
272+
address_part = match.group(2)
273+
# For 2-part tags, use the address as the tag_name
274+
return AddressTag(tag_type, address_part, value.strip())
275+
276+
# Regular address string
277+
return Address(value, left_padding=True)
262278

263279

264280
def parse_address_or_tag_for_access_list(value: Any) -> Union[Address, str]:
@@ -271,7 +287,7 @@ def parse_address_or_tag_for_access_list(value: Any) -> Union[Address, str]:
271287
return Address(value, left_padding=True)
272288

273289
# Check if it matches a tag pattern
274-
tag_pattern = r"^<(eoa|contract):.+>$"
290+
tag_pattern = r"^<(eoa|contract|coinbase):.+>$"
275291
if re.match(tag_pattern, value.strip()):
276292
# Return the tag string as-is for later resolution
277293
return value.strip()

src/ethereum_test_specs/static_state/environment.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22

33
from pydantic import BaseModel, Field, model_validator
44

5-
from .common import AddressInFiller, ValueInFiller
5+
from .common import AddressOrTagInFiller, ValueInFiller
66

77

88
class EnvironmentInStateTestFiller(BaseModel):
99
"""Class that represents an environment filler."""
1010

11-
current_coinbase: AddressInFiller = Field(..., alias="currentCoinbase")
11+
current_coinbase: AddressOrTagInFiller = Field(..., alias="currentCoinbase")
1212
current_gas_limit: ValueInFiller = Field(..., alias="currentGasLimit")
1313
current_number: ValueInFiller = Field(..., alias="currentNumber")
1414
current_timestamp: ValueInFiller = Field(..., alias="currentTimestamp")

src/ethereum_test_specs/static_state/state_static.py

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,15 @@ def _resolve_address_or_tag(self, value: Any, test_id: str, fork: Fork) -> Any:
108108
if parsed.tag_type == "contract":
109109
# Use deploy_contract to get next contract address
110110
# We'll deploy with empty code for now, just to reserve the address
111-
address = alloc.deploy_contract(code=b"")
112-
self._tag_to_address_map[test_id][parsed.original_string] = address
113-
return address
111+
if parsed.tag_name == "sender":
112+
eoa = alloc.fund_eoa(amount=0)
113+
self._tag_to_address_map[test_id][parsed.original_string] = Address(eoa)
114+
self._tag_to_eoa_map[test_id][parsed.original_string] = eoa
115+
return Address(eoa)
116+
else:
117+
address = alloc.deploy_contract(code=b"")
118+
self._tag_to_address_map[test_id][parsed.original_string] = address
119+
return address
114120
elif parsed.tag_type == "eoa":
115121
# Use fund_eoa to get next EOA
116122
eoa = alloc.fund_eoa(amount=0) # Don't fund yet, just get the address
@@ -126,30 +132,21 @@ def _resolve_address_or_tag(self, value: Any, test_id: str, fork: Fork) -> Any:
126132
def _resolve_tags_in_code(self, code_str: str, test_id: str, fork: Fork) -> str:
127133
"""Resolve address tags in code strings before compilation."""
128134
tag_pattern = r"<(eoa|contract):[^>]+>"
129-
is_raw_hex = ":raw" in code_str
130135

131136
def replace_tag(match):
132137
tag_str = match.group(0)
133138
parsed = parse_address_or_tag(tag_str)
134139
if isinstance(parsed, AddressTag):
135140
address = self._resolve_address_or_tag(tag_str, test_id, fork)
136-
137-
# For :raw format, always return address without 0x prefix
138-
if is_raw_hex:
139-
return str(address)[2:]
140-
141-
# For other formats, check if we're inside a hex string
142141
start_pos = match.start()
143-
# Find the last occurrence of '0x' before the tag
144-
prefix_pos = code_str.rfind("0x", 0, start_pos)
145-
if prefix_pos != -1:
146-
# Check if all characters between '0x' and the tag are hex digits
147-
between_content = code_str[prefix_pos + 2 : start_pos]
148-
if all(c in "0123456789abcdefABCDEF" for c in between_content):
149-
# We're inside bytecode, return address without 0x prefix
150-
return str(address)[2:]
151-
152-
# Default: return the address as hex string with 0x prefix
142+
preceeding_2chars = code_str[start_pos - 2 : start_pos]
143+
if not (
144+
preceeding_2chars == "0x" or any(kw in preceeding_2chars for kw in [" ", "("])
145+
):
146+
# - If the tag is not preceded by 0x, we're inside a hex string
147+
# - If the tag is preceded by a space, we'd need the 0x prefix
148+
# return the address without the 0x prefix
149+
return str(address)[2:]
153150
return str(address)
154151
return tag_str
155152

@@ -322,7 +319,7 @@ def _make_vector(
322319
# Get the same registry key logic as _get_alloc_for_test
323320
for addr_str in self.pre.keys():
324321
parsed = parse_address_or_tag(addr_str)
325-
if isinstance(parsed, AddressTag) and parsed.tag_type == "eoa":
322+
if isinstance(parsed, AddressTag) and parsed.tag_name == "sender":
326323
# Found the sender EOA - get it from our registry
327324
if parsed.original_string in self._tag_to_eoa_map.get(test_id, {}):
328325
sender_eoa = self._tag_to_eoa_map[test_id][parsed.original_string]
@@ -335,10 +332,13 @@ def _make_vector(
335332
if isinstance(general_tr.secret_key, str) and general_tr.secret_key.startswith(
336333
"<sender:key:"
337334
):
338-
# This should not never happen so fail hard here as a sanity check
339-
raise ValueError(
340-
"Test has sender key tag but no corresponding EOA tag in pre state"
341-
)
335+
# Perhaps this is a test that is trying to test non-existing accounts,
336+
# use a generated EOA's key anyhow, funded as `0` (since not in pre state)
337+
sender_eoa = self._get_alloc_for_test(test_id, fork).fund_eoa(amount=0)
338+
if sender_eoa.key is not None:
339+
secret_key_to_use = sender_eoa.key
340+
else:
341+
raise ValueError(f"Sender EOA has no key: {sender_eoa}")
342342
else:
343343
# This is a test that has not been converted to use tagging either
344344
# because it needs hard-coded addresses or because of some other reason.

test_empty_blob.yml

Lines changed: 0 additions & 63 deletions
This file was deleted.

0 commit comments

Comments
 (0)