Skip to content

Commit a63fab6

Browse files
committed
fork is now passed as object, timestamp is part of filename, created static_blobs for all forks, fixed uv.lock
1 parent e30e319 commit a63fab6

33 files changed

+784
-856
lines changed

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ dependencies = [
2828
"requests>=2.31.0,<3",
2929
"requests_unixsocket2>=0.4.0",
3030
"colorlog>=6.7.0,<7",
31-
"pytest>7.3.2,<8",
31+
"pytest>=8,<9",
3232
"pytest-custom-report>=1.0.1,<2",
3333
"pytest-html>=4.1.0,<5",
3434
"pytest-metadata>=3,<4",
@@ -50,7 +50,7 @@ dependencies = [
5050
"pytest-regex>=0.2.0,<0.3",
5151
"eth-abi>=5.2.0",
5252
"joblib>=1.4.2",
53-
"ckzg>=2.1.1"
53+
"ckzg>=2.1.1",
5454
]
5555

5656
[project.urls]

src/ethereum_test_types/blob.py

Lines changed: 105 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
from ethereum_test_base_types.base_types import Bytes, Hash
1717
from ethereum_test_base_types.pydantic import CamelModel
18+
from ethereum_test_forks import Cancun, Fork, Osaka, Prague
1819

1920
sys.path.insert(0, abspath(join(dirname(__file__), "../../"))) # TODO: find better workaround
2021
from tests.osaka.eip7594_peerdas.spec import Spec, ref_spec_7594
@@ -55,9 +56,9 @@ class Blob(CamelModel):
5556
timestamp: int
5657

5758
@staticmethod
58-
def get_filepath(fork: str, seed: int):
59+
def get_filepath(fork: str, seed: int, timestamp: int):
5960
"""Return the Path to the blob that would be created with these parameters."""
60-
would_be_filename: str = "blob_" + fork + "_" + str(seed) + ".json"
61+
would_be_filename: str = "blob_" + fork + "_" + str(seed) + "_" + str(timestamp) + ".json"
6162
assert fork in ["cancun", "prague", "osaka"], f"Fork {fork} not implemented yet"
6263

6364
if fork == "osaka":
@@ -85,10 +86,12 @@ def get_filepath(fork: str, seed: int):
8586
return would_be_static_blob_path
8687

8788
@staticmethod
88-
def NewBlob(fork: str, seed: int = 0, timestamp: int = 0) -> "Blob": # noqa: N802
89+
def NewBlob(fork: Fork, seed: int = 0, timestamp: int = 0) -> "Blob": # noqa: N802
8990
"""Construct Blob instances. Fork-specific logic is encapsulated within nested functions.""" # noqa: E501
91+
fork_str: str = fork.name().lower()
92+
9093
# if this blob already exists then load from file
91-
blob_location: Path = Blob.get_filepath(fork, seed)
94+
blob_location: Path = Blob.get_filepath(fork_str, seed, timestamp)
9295
if blob_location.exists():
9396
print(f"Blob exists already, reading it from file {blob_location}")
9497
return Blob.LoadBlobFromFile(str(blob_location))
@@ -115,9 +118,9 @@ def get_versioned_hash(commitment: Bytes, version: int = 1) -> Hash:
115118
# TODO: is this in specs or made up by us? do we need it?
116119
return Hash(bytes([version]) + sha256(commitment).digest()[1:])
117120

118-
def get_name(seed: int) -> str:
121+
def get_name(fork_str: str, seed: int, timestamp: int) -> str:
119122
"""Derive blob name from the seed that generates its data."""
120-
return "blob_" + fork + "_" + str(seed)
123+
return "blob_" + fork_str + "_" + str(seed) + "_" + str(timestamp)
121124

122125
def get_commitment(data: Bytes) -> Bytes:
123126
"""Take a blob and returns a cryptographic commitment to it. Note: Each cell seems to hold a copy of this commitment.""" # noqa: E501
@@ -136,39 +139,39 @@ def get_commitment(data: Bytes) -> Bytes:
136139
return commitment
137140

138141
def get_proof(data: Bytes) -> List[Bytes] | Bytes:
139-
if fork in ["cancun", "prague"]:
142+
if fork_str in ["cancun", "prague"]:
140143
z = 2 # 2 is one of many possible valid field elements z (https://github.com/ethereum/consensus-specs/blob/ad884507f7a1d5962cd3dfb5f7b3e41aab728c55/tests/core/pyspec/eth2spec/test/utils/kzg_tests.py#L58-L66)
141144
z_valid_size: bytes = z.to_bytes(Spec.BYTES_PER_FIELD_ELEMENT, byteorder="big")
142145
proof, _ = ckzg.compute_kzg_proof(data, z_valid_size, TRUSTED_SETUP)
143146
return proof
144147

145-
if fork in ["osaka"]:
148+
if fork_str in ["osaka"]:
146149
_, proofs = ckzg.compute_cells_and_kzg_proofs(
147150
data, TRUSTED_SETUP
148151
) # returns List[byte] of length 128
149152
return proofs # List[bytes] # TODO: how to convert List[bytes] to List[Bytes], do we even care about bytes vs Bytes? # noqa: E501
150153

151-
raise AssertionError(f"get_proof() has not been implemented yet for fork: {fork}")
154+
raise AssertionError(f"get_proof() has not been implemented yet for fork: {fork_str}")
152155

153156
def get_cells(data: Bytes) -> List[Bytes] | None:
154-
if fork in ["cancun", "prague"]:
157+
if fork_str in ["cancun", "prague"]:
155158
return None
156159

157-
if fork in ["osaka"]:
160+
if fork_str in ["osaka"]:
158161
cells, _ = ckzg.compute_cells_and_kzg_proofs(
159162
data, TRUSTED_SETUP
160163
) # returns List[byte] of length 128
161164
return cells # List[bytes] # TODO: how to convert List[bytes] to List[Bytes]
162165

163-
raise AssertionError(f"get_cells() has not been implemented yet for fork: {fork}")
166+
raise AssertionError(f"get_cells() has not been implemented yet for fork: {fork_str}")
164167

165168
# populate blob fields
166169
data: Bytes = generate_blob_data(seed)
167170
commitment: Bytes = get_commitment(data)
168171
proof: List[Bytes] | Bytes = get_proof(data)
169172
cells: List[Bytes] | None = get_cells(data)
170173
versioned_hash: Hash = get_versioned_hash(commitment)
171-
name: str = get_name(seed)
174+
name: str = get_name(fork_str, seed, timestamp)
172175

173176
return Blob(
174177
data=data,
@@ -177,7 +180,7 @@ def get_cells(data: Bytes) -> List[Bytes] | None:
177180
cells=cells,
178181
versioned_hash=versioned_hash,
179182
name=name,
180-
fork=fork,
183+
fork=fork_str,
181184
seed=seed,
182185
timestamp=timestamp,
183186
)
@@ -190,13 +193,23 @@ def LoadBlobFromFile(file_path: str) -> "Blob": # noqa: N802
190193

191194
# determine whether user passed only filename or entire path
192195
if file_path.startswith("blob_"):
196+
print(f"Received file_path: {file_path}")
193197
parts = file_path.split("_")
198+
assert len(parts) == 4, (
199+
f"You provided an invalid filename. Each blob is named blob_<fork>_<seed>_<timestamp>.json but you provided: {file_path}" # noqa: E501
200+
)
194201
detected_fork = parts[1]
195-
detected_seed = parts[2].removesuffix(".json")
202+
detected_seed = parts[2]
203+
detected_timestamp = parts[3].removesuffix(".json")
196204
assert detected_seed.isdigit(), (
197205
f"Failed to extract seed from filename. Ended up with seed {detected_seed} given filename {file_path}" # noqa: E501
198206
)
199-
file_path = Blob.get_filepath(detected_fork, int(detected_seed))
207+
assert detected_timestamp.isdigit(), (
208+
f"Failed to extract timestamp from filename. Ended up with timestamp {detected_timestamp} given filename {file_path}" # noqa: E501
209+
)
210+
file_path = Blob.get_filepath(
211+
detected_fork, int(detected_seed), int(detected_timestamp)
212+
)
200213

201214
assert Path(file_path).exists(), (
202215
f"Tried to load static blob from file but {file_path} does not exist"
@@ -211,7 +224,7 @@ def LoadBlobFromFile(file_path: str) -> "Blob": # noqa: N802
211224
def write_to_file(self):
212225
"""Take a blob object, serialize it and write it to disk as json."""
213226
json_str = self.model_dump_json()
214-
output_location = Blob.get_filepath(self.fork, self.seed)
227+
output_location = Blob.get_filepath(self.fork, self.seed, self.timestamp)
215228

216229
# warn if existing static_blob gets overwritten
217230
if output_location.exists():
@@ -355,76 +368,94 @@ def corrupt_byte(b: bytes) -> Bytes:
355368
self.proof = Bytes(b"".join(corrupt_byte(bytes([byte])) for byte in self.proof))
356369

357370

358-
# TODO: instead of defining fork via string pass fork object and derive string
359-
# TODO: generate 10 static blobs for osaka, and 10 for cancun/prague, location is folder of respective eips
360-
# TODO: remove uv lock and pyproject.toml changes from this PR, then make separate pr for adding czkg dependency
361-
# TODO: update test_blob_txs_full.py to make use of actual blobs
362-
363-
# fork: str = "prague"
364-
myseed: int = 1337 # fork+seed is the unique ID of a blob
365-
b: Blob = Blob.NewBlob("prague", myseed)
366-
json_str: str = b.model_dump_json()
367-
restored: Blob = Blob.model_validate_json(json_str)
368-
assert b.data == restored.data
369-
assert b.commitment == restored.commitment
370-
assert b.proof == restored.proof
371-
assert b.cells == restored.cells
372-
assert b.versioned_hash == restored.versioned_hash
373-
assert b.name == restored.name
374-
assert b.fork == restored.fork
375-
assert b.timestamp == restored.timestamp
376-
print(type(b.proof), len(b.proof))
377-
print(Spec.BYTES_PER_FIELD_ELEMENT)
378-
print(len(b.data))
379-
380-
b.write_to_file()
381-
c: Blob = Blob.LoadBlobFromFile(
382-
"blob_" + "prague" + "_" + str(myseed)
383-
) # or just put filename blob_osaka_1337
384-
assert b.data == c.data
385-
assert b.commitment == c.commitment
386-
assert b.proof == c.proof
387-
assert b.cells == c.cells
388-
assert b.versioned_hash == c.versioned_hash
389-
assert b.name == c.name
390-
assert b.fork == c.fork
391-
assert b.timestamp == c.timestamp
392-
393-
e: Blob = Blob.NewBlob("prague", myseed)
394-
print("Line above should say blob already existed and was loaded from file")
395-
f: Blob = Blob.NewBlob("cancun", myseed)
396-
f.write_to_file()
397-
g: Blob = Blob.NewBlob("cancun", myseed)
398-
print("Line above should say blob already existed and was loaded from file")
399-
h: Blob = Blob.NewBlob("osaka", myseed)
400-
h.write_to_file()
401-
zz: Blob = Blob.NewBlob("osaka", myseed)
402-
print("Line above should say blob already existed and was loaded from file")
403-
404-
# you can load a blob either via just filename or via absolute path or via relative path (cwd is ./src/ethereum_test_types) # noqa: E501
405-
yyy: Blob = Blob.LoadBlobFromFile("blob_cancun_1337.json")
406-
# yyyy: Blob = Blob.LoadBlobFromFile(
407-
# "/home/user/Documents/execution-spec-tests/tests/cancun/eip4844_blobs/static_blobs/blob_cancun_1337.json" # noqa: E501
408-
# ) # you must replace user with ur actual username as $USER not supported here
409-
yyyyy: Blob = Blob.LoadBlobFromFile(
410-
"../../tests/cancun/eip4844_blobs/static_blobs/blob_cancun_1337.json"
411-
)
371+
# TODO: currently u can only run this file from ./blob.py but not from eest root, fix it
372+
373+
# TODO after merge: update test_blob_txs_full.py to make use of actual blobs
374+
375+
# --------- generate static blobs ------------
376+
# fork_list = [Cancun, Prague, Osaka]
377+
# amount_static_blobs_per_fork = 10
378+
# for f in fork_list:
379+
# for seed in range(amount_static_blobs_per_fork):
380+
# if seed < 4:
381+
# timestamp = 0
382+
# elif seed < 7:
383+
# timestamp = 1000000000
384+
# else:
385+
# timestamp = 1747905411
386+
387+
# static_blob: Blob = Blob.NewBlob(f, seed, timestamp)
388+
# static_blob.write_to_file()
389+
# --------------------------------------------
390+
391+
# myosaka: Fork = Osaka
392+
# myprague: Fork = Prague
393+
# mycancun: Fork = Cancun
394+
# myseed: int = 1337 # fork+seed is the unique ID of a blob
395+
# mytimestamp: int = 168123123
396+
# b: Blob = Blob.NewBlob(myosaka, myseed, mytimestamp)
397+
# json_str: str = b.model_dump_json()
398+
# restored: Blob = Blob.model_validate_json(json_str)
399+
# assert b.data == restored.data
400+
# assert b.commitment == restored.commitment
401+
# assert b.proof == restored.proof
402+
# assert b.cells == restored.cells
403+
# assert b.versioned_hash == restored.versioned_hash
404+
# assert b.name == restored.name
405+
# assert b.fork == restored.fork
406+
# assert b.timestamp == restored.timestamp
407+
# print(type(b.proof), len(b.proof))
408+
# print(Spec.BYTES_PER_FIELD_ELEMENT)
409+
# print(len(b.data))
410+
# b.write_to_file()
411+
# c: Blob = Blob.LoadBlobFromFile(
412+
# "blob_" + "osaka" + "_" + str(myseed) + "_" + str(mytimestamp)
413+
# )
414+
# assert b.data == c.data
415+
# assert b.commitment == c.commitment
416+
# assert b.proof == c.proof
417+
# assert b.cells == c.cells
418+
# assert b.versioned_hash == c.versioned_hash
419+
# assert b.name == c.name
420+
# assert b.fork == c.fork
421+
# assert b.timestamp == c.timestamp
422+
# d: Blob = Blob.NewBlob(myprague, myseed, 123)
423+
# d.write_to_file()
424+
# e: Blob = Blob.NewBlob(myprague, myseed, 123)
425+
# print("Line above should say blob already existed and was loaded from file")
426+
# ee: Blob = Blob.NewBlob(myprague, myseed, 1234)
427+
# newtimestamp = 999999
428+
# f: Blob = Blob.NewBlob(mycancun, 1337, newtimestamp)
429+
# f.write_to_file()
430+
# h: Blob = Blob.NewBlob(myosaka, myseed)
431+
# h.write_to_file()
432+
# zz: Blob = Blob.NewBlob(myosaka, myseed)
433+
# print("Line above should say blob already existed and was loaded from file")
434+
# # you can load a blob either via just filename or via absolute path or via relative path (cwd is ./src/ethereum_test_types) # noqa: E501
435+
# yyy: Blob = Blob.LoadBlobFromFile("blob_cancun_1337_999999.json")
436+
# # yyyy: Blob = Blob.LoadBlobFromFile(
437+
# # "/home/user/Documents/execution-spec-tests/tests/cancun/eip4844_blobs/static_blobs/blob_cancun_1337.json" # noqa: E501
438+
# # ) # you must replace user with ur actual username as $USER not supported here
439+
# yyyyy: Blob = Blob.LoadBlobFromFile(
440+
# "../../tests/cancun/eip4844_blobs/static_blobs/blob_cancun_1337_999999.json"
441+
# )
412442

413443

414444
# # test proof corruption
415445
# # osaka
416-
# d: Blob = Blob.NewBlob("osaka", seed + 10)
446+
# testseed = 55
447+
# d: Blob = Blob.NewBlob(Osaka, testseed + 10)
417448
# oldValue = d.proof[0][5]
418449
# for m in Blob.ProofCorruptionMode:
419450
# d.corrupt_proof(m)
420451
# print("proof corruption works (osaka):", oldValue != d.proof[0][5])
421452
# # prague
422-
# e: Blob = Blob.NewBlob("prague", seed + 11)
453+
# e: Blob = Blob.NewBlob(Prague, testseed + 11)
423454
# oldValue = e.proof[5]
424455
# for m in Blob.ProofCorruptionMode:
425456
# e.corrupt_proof(m)
426457
# print("proof corruption works (prague):", oldValue != e.proof[5])
427-
print("pydantic model works")
458+
# print("pydantic model works")
428459

429460
# ckzg.compute_cells(blob, TRUSTED_SETUP) returns a list of length 128
430461
# ckzg.compute_cells_and_kzg_proofs(blob, TRUSTED_SETUP)

tests/cancun/eip4844_blobs/static_blobs/blob_cancun_0_0.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

tests/cancun/eip4844_blobs/static_blobs/blob_cancun_1_0.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

tests/cancun/eip4844_blobs/static_blobs/blob_cancun_2_0.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

tests/cancun/eip4844_blobs/static_blobs/blob_cancun_3_0.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

tests/cancun/eip4844_blobs/static_blobs/blob_cancun_4_1000000000.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

tests/cancun/eip4844_blobs/static_blobs/blob_cancun_5_1000000000.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

tests/cancun/eip4844_blobs/static_blobs/blob_cancun_6_1000000000.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

tests/cancun/eip4844_blobs/static_blobs/blob_cancun_7_1747905411.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)