1515
1616from ethereum_test_base_types .base_types import Bytes , Hash
1717from ethereum_test_base_types .pydantic import CamelModel
18+ from ethereum_test_forks import Cancun , Fork , Osaka , Prague
1819
1920sys .path .insert (0 , abspath (join (dirname (__file__ ), "../../" ))) # TODO: find better workaround
2021from 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)
0 commit comments