@@ -260,6 +260,15 @@ def must_be_equal(self, other: "Storage"):
260260 raise Storage .KeyValueMismatch (key , 0 , other .data [key ])
261261
262262
263+ def storage_padding (storage : Dict ) -> Dict :
264+ """
265+ Adds even padding to each storage element.
266+ """
267+ return {
268+ key_value_padding (k ): key_value_padding (v ) for k , v in storage .items ()
269+ }
270+
271+
263272@dataclass (kw_only = True )
264273class Account :
265274 """
@@ -425,6 +434,22 @@ def with_code(cls: Type, code: bytes | str | Code) -> "Account":
425434 return Account (nonce = 1 , code = code )
426435
427436
437+ def alloc_to_accounts (got_alloc : Dict [str , Any ]) -> Mapping [str , Account ]:
438+ """
439+ Converts the post state alloc returned from t8n to a mapping of accounts.
440+ """
441+ accounts = {}
442+ for address , value in got_alloc .items ():
443+ account = Account (
444+ nonce = int_or_none (value .get ("nonce" , None )),
445+ balance = int_or_none (value .get ("balance" , None )),
446+ code = value .get ("code" , None ),
447+ storage = value .get ("storage" , None ),
448+ )
449+ accounts [address ] = account
450+ return accounts
451+
452+
428453ACCOUNT_DEFAULTS = Account (nonce = 0 , balance = 0 , code = bytes (), storage = {})
429454
430455
@@ -832,7 +857,9 @@ class FixtureBlock:
832857 block_header : Optional [FixtureHeader ] = None
833858 expected_exception : Optional [str ] = None
834859 block_number : Optional [int ] = None
835- chain_name : Optional [str ] = None
860+ txs : Optional [List [Transaction ]] = None
861+ ommers : Optional [List [Header ]] = None
862+ withdrawals : Optional [List [Withdrawal ]] = None
836863
837864
838865@dataclass (kw_only = True )
@@ -879,9 +906,9 @@ def default(self, obj):
879906 obj .balance , hex (ACCOUNT_DEFAULTS .balance )
880907 ),
881908 "code" : code_or_none (obj .code , "0x" ),
882- "storage" : to_json_or_none (obj .storage , {}),
909+ "storage" : storage_padding ( to_json_or_none (obj .storage , {}) ),
883910 }
884- return account
911+ return even_padding ( account , excluded = [ "storage" ])
885912 elif isinstance (obj , Transaction ):
886913 tx = {
887914 "type" : hex (obj .ty ),
@@ -912,12 +939,13 @@ def default(self, obj):
912939
913940 return {k : v for (k , v ) in tx .items () if v is not None }
914941 elif isinstance (obj , Withdrawal ):
915- return {
942+ withdrawal = {
916943 "index" : hex (obj .index ),
917944 "validatorIndex" : hex (obj .validator ),
918945 "address" : obj .address ,
919946 "amount" : hex (obj .amount ),
920947 }
948+ return withdrawal
921949 elif isinstance (obj , Environment ):
922950 env = {
923951 "currentCoinbase" : obj .coinbase ,
@@ -967,11 +995,52 @@ def default(self, obj):
967995 header ["hash" ] = obj .hash
968996 if obj .withdrawals_root is not None :
969997 header ["withdrawalsRoot" ] = obj .withdrawals_root
970- return header
998+ return even_padding (
999+ header ,
1000+ excluded = [
1001+ "parentHash" ,
1002+ "uncleHash" ,
1003+ "coinbase" ,
1004+ "transactionsTrie" ,
1005+ "receiptTrie" ,
1006+ "bloom" ,
1007+ "nonce" ,
1008+ "mixHash" ,
1009+ "hash" ,
1010+ "withdrawalsRoot" ,
1011+ ],
1012+ )
9711013 elif isinstance (obj , FixtureBlock ):
972- b = {
973- "rlp" : obj .rlp ,
974- }
1014+ # Format Fixture Block Txs
1015+ b_txs = [
1016+ even_padding (
1017+ to_json (
1018+ {
1019+ "nonce" : hex (tx .nonce ),
1020+ "to" : tx .to if tx .to is not None else "" ,
1021+ "value" : hex (tx .value ),
1022+ "data" : code_to_hex (tx .data ),
1023+ "gasLimit" : hex_or_none (tx .gas_limit ),
1024+ "gasPrice" : hex (tx .gas_price )
1025+ if tx .gas_price is not None
1026+ else "0x0A" ,
1027+ "secretKey" : tx .secret_key ,
1028+ }
1029+ ),
1030+ excluded = ["to" ],
1031+ )
1032+ for tx in obj .txs or []
1033+ ]
1034+
1035+ # Format Fixture Block Withdrawals
1036+ b_wds = []
1037+ if obj .withdrawals :
1038+ b_wds = [
1039+ even_padding (to_json (wd ), excluded = ["address" ])
1040+ for wd in obj .withdrawals
1041+ ]
1042+
1043+ b = {"rlp" : obj .rlp }
9751044 if obj .block_header is not None :
9761045 b ["blockHeader" ] = json .loads (
9771046 json .dumps (obj .block_header , cls = JSONEncoder )
@@ -980,8 +1049,12 @@ def default(self, obj):
9801049 b ["expectException" ] = obj .expected_exception
9811050 if obj .block_number is not None :
9821051 b ["blocknumber" ] = str (obj .block_number )
983- if obj .chain_name is not None :
984- b ["chainname" ] = obj .chain_name
1052+ if obj .txs is not None :
1053+ b ["transactions" ] = b_txs
1054+ if obj .ommers is not None :
1055+ b ["uncleHeaders" ] = obj .ommers
1056+ if obj .withdrawals is not None :
1057+ b ["withdrawals" ] = b_wds
9851058 return b
9861059 elif isinstance (obj , Fixture ):
9871060 f = {
@@ -1005,3 +1078,32 @@ def default(self, obj):
10051078 return f
10061079 else :
10071080 return super ().default (obj )
1081+
1082+
1083+ def even_padding (input : Dict , excluded : List [Any | None ]) -> Dict :
1084+ """
1085+ Adds even padding to each field in the input (nested) dictionary.
1086+ """
1087+ for key , value in input .items ():
1088+ if key not in excluded :
1089+ if isinstance (value , dict ):
1090+ even_padding (value , excluded )
1091+ elif value != "0x" and value is not None :
1092+ input [key ] = key_value_padding (value )
1093+ else :
1094+ input [key ] = "0x"
1095+ return input
1096+
1097+
1098+ def key_value_padding (value : str ) -> str :
1099+ """
1100+ Adds even padding to a dictionary key or value string.
1101+ """
1102+ if value is not None :
1103+ new_value = value .lstrip ("0x" ).lstrip ("0" )
1104+ new_value = "00" if new_value == "" else new_value
1105+ if len (new_value ) % 2 == 1 :
1106+ new_value = "0" + new_value
1107+ return "0x" + new_value
1108+ else :
1109+ return "0x"
0 commit comments