@@ -46,6 +46,7 @@ class GethKeys:
4646 headerHashSuffix = b'n'
4747
4848 blockBodyPrefix = b'b'
49+ blockReceiptsPrefix = b'r'
4950
5051 @classmethod
5152 def header_hash_for_block_number (cls , block_number : int ) -> bytes :
@@ -68,6 +69,11 @@ def block_body(cls, block_number: int, header_hash: bytes) -> bytes:
6869 packed_block_number = struct .pack ('>Q' , block_number )
6970 return cls .blockBodyPrefix + packed_block_number + header_hash
7071
72+ @classmethod
73+ def block_receipts (cls , block_number : int , header_hash : bytes ) -> bytes :
74+ packed_block_number = struct .pack ('>Q' , block_number )
75+ return cls .blockReceiptsPrefix + packed_block_number + header_hash
76+
7177
7278class GethFreezerIndexEntry :
7379 def __init__ (self , filenum : int , offset : int ):
@@ -182,6 +188,7 @@ def __init__(self, path):
182188 self .ancient_hashes = GethFreezerTable (ancient_path , 'hashes' , False )
183189 self .ancient_headers = GethFreezerTable (ancient_path , 'headers' , True )
184190 self .ancient_bodies = GethFreezerTable (ancient_path , 'bodies' , True )
191+ self .ancient_receipts = GethFreezerTable (ancient_path , 'receipts' , True )
185192
186193 if self .database_version != b'\x07 ' :
187194 raise Exception (f'geth database version { self .database_version } is not supported' )
@@ -230,6 +237,17 @@ def block_body(self, block_number: int, header_hash: bytes = None):
230237 raw_data = self .ancient_bodies .get (block_number )
231238 return rlp .decode (raw_data , sedes = BlockBody )
232239
240+ def block_receipts (self , block_number : int , header_hash : bytes = None ):
241+ if header_hash is None :
242+ header_hash = self .header_hash_for_block_number (block_number )
243+
244+ raw_data = self .db .get (GethKeys .block_receipts (block_number , header_hash ))
245+ if raw_data is not None :
246+ return raw_data
247+
248+ raw_data = self .ancient_receipts .get (block_number )
249+ return raw_data
250+
233251
234252class ImportDatabase :
235253 "Creates a 'ChainDB' which can be passed to the trie_iteration utils"
@@ -455,6 +473,22 @@ def process_blocks(gethdb, chain, end_block):
455473 logger .debug (f'imported block: { imported_block } ' )
456474
457475
476+ def read_receipts (gethdb , block_number ):
477+ logger .info (f'reading receipts for block. block_number={ block_number } ' )
478+
479+ raw_data = gethdb .block_receipts (block_number )
480+ decoded = rlp .decode (raw_data )
481+
482+ logger .info (f'- receipt_count={ len (decoded )} ' )
483+
484+ for receipt in decoded :
485+ post_state , raw_gas_used , logs = receipt
486+ if len (raw_gas_used ) < 8 :
487+ padded = (b'\x00 ' * (8 - len (raw_gas_used ))) + raw_gas_used
488+ gas_used = struct .unpack ('>Q' , padded )[0 ]
489+ logger .info (f'- post_state_or_status={ post_state } gas_used={ gas_used } len(logs)={ len (logs )} ' )
490+
491+
458492if __name__ == "__main__" :
459493 logging .basicConfig (
460494 level = logging .DEBUG ,
@@ -478,6 +512,9 @@ def process_blocks(gethdb, chain, end_block):
478512 process_blocks_parser = subparsers .add_parser ('process_blocks' )
479513 process_blocks_parser .add_argument ('-endblock' , type = int , required = True )
480514
515+ read_receipts_parser = subparsers .add_parser ('read_receipts' )
516+ read_receipts_parser .add_argument ('-block' , type = int , required = True )
517+
481518 args = parser .parse_args ()
482519
483520 if args .command == 'import_body_range' :
@@ -488,6 +525,9 @@ def process_blocks(gethdb, chain, end_block):
488525 gethdb = open_gethdb (args .gethdb )
489526 chain = open_trinitydb (args .destdb )
490527 process_blocks (gethdb , chain , args .endblock )
528+ elif args .command == 'read_receipts' :
529+ gethdb = open_gethdb (args .gethdb )
530+ read_receipts (gethdb , args .block )
491531 else :
492532 main (args )
493533
0 commit comments